This is page 1 of 5. Use http://codebase.md/bucketco/docs/_media/type-check-failed.png%20%22Type%20check%20failed%22?page={x} to view the full context.
# Directory Structure
```
├── .gitbook
│ ├── assets
│ │ ├── 03642c5-dwFrame_201 (1).png
│ │ ├── 03642c5-dwFrame_201.png
│ │ ├── 1753259671871 (1).jpeg
│ │ ├── 1a0b50d-image.png
│ │ ├── 1a439d9-image.png
│ │ ├── 2506596-Customized_Widgets.png
│ │ ├── 342658e-image.png
│ │ ├── 4017197-image.png
│ │ ├── 43e55f0-image.png
│ │ ├── 4783e3f-image.png
│ │ ├── 5b0ce63-image (1).png
│ │ ├── 5b0ce63-image.png
│ │ ├── 630b5e9-image.png
│ │ ├── 8bf8a6e-Frame_201.png
│ │ ├── 9efd67c-image.png
│ │ ├── aa37226-image.png
│ │ ├── Access (1) (1).png
│ │ ├── Access (1).png
│ │ ├── Access (2).png
│ │ ├── Access.png
│ │ ├── Adding features to a feature view-min.png
│ │ ├── Adopted-min.png
│ │ ├── Adoption strategy V2-min.png
│ │ ├── Adoption strategy-min.png
│ │ ├── Advanced targeting rules V2-min.png
│ │ ├── Advanced targeting rules v3-min.png
│ │ ├── Advanced targeting rules-min.png
│ │ ├── aecc6f2-image.png
│ │ ├── amplitude.svg
│ │ ├── An example targeting configuration with two rules.-min.png
│ │ ├── api.svg
│ │ ├── App Settings-min.png
│ │ ├── Automated feedback surveys settings v3-min.png
│ │ ├── Automated feedback surveys settings-min.png
│ │ ├── Automated feedback surveys-min.png
│ │ ├── aws-s3.svg
│ │ ├── be124cd-dwdwFrame_201 (1).png
│ │ ├── be124cd-dwdwFrame_201.png
│ │ ├── ccc4f9e-image.png
│ │ ├── CleanShot 2024-06-11 at 8 [email protected]
│ │ ├── CleanShot 2024-11-22 at 8 [email protected]
│ │ ├── CleanShot 2024-11-22 at 8 [email protected]
│ │ ├── CleanShot 2024-11-25 at 9 [email protected]
│ │ ├── CleanShot 2024-11-25 at 9 [email protected]
│ │ ├── CleanShot 2024-11-25 at 9 [email protected]
│ │ ├── CleanShot 2024-11-27 at 10 [email protected]
│ │ ├── CleanShot 2024-11-27 at 10 [email protected]
│ │ ├── CleanShot 2024-11-27 at 10 [email protected]
│ │ ├── CleanShot 2024-11-27 at 10 [email protected]
│ │ ├── CleanShot 2025-01-07 at 1 [email protected]
│ │ ├── CleanShot 2025-01-07 at 1 [email protected]
│ │ ├── CleanShot 2025-01-07 at 1 [email protected]
│ │ ├── CleanShot 2025-01-07 at 12 [email protected]
│ │ ├── CleanShot 2025-01-07 at 12 .39.12@2x (1).png
│ │ ├── CleanShot 2025-01-07 at 12 [email protected]
│ │ ├── CleanShot 2025-01-09 at 10 [email protected]
│ │ ├── CleanShot 2025-01-09 at 11 .11.54@2x (1).png
│ │ ├── CleanShot 2025-01-09 at 11 [email protected]
│ │ ├── CleanShot 2025-01-09 at 9 [email protected]
│ │ ├── CleanShot 2025-01-23 at 1 [email protected]
│ │ ├── CleanShot 2025-01-23 at 1 [email protected]
│ │ ├── CleanShot 2025-01-23 at 1 [email protected]
│ │ ├── CleanShot 2025-01-23 at 2 [email protected]
│ │ ├── CleanShot 2025-05-09 at 1 [email protected]
│ │ ├── CleanShot 2025-10-09 at 10 [email protected]
│ │ ├── Companies Tab-min.png
│ │ ├── Companies-min.png
│ │ ├── company example v2-min (1).png
│ │ ├── company example v2-min.png
│ │ ├── company example v3-min.png
│ │ ├── Company segment filters-min.png
│ │ ├── Create a new environment-min.png
│ │ ├── Creating and managing apps-min.png
│ │ ├── cursor-mcp-demo_h264.mp4
│ │ ├── datadog.svg
│ │ ├── Debugger-min (1).png
│ │ ├── Debugger-min (2).png
│ │ ├── Debugger-min.png
│ │ ├── Enabling Feedback Surveys-min.png
│ │ ├── Environments Page V2-min.png
│ │ ├── Environments Switcher-min.png
│ │ ├── Environments-min.png
│ │ ├── Evaluate Feature.png
│ │ ├── example 1 (1).png
│ │ ├── example 1.png
│ │ ├── example 2 (1).png
│ │ ├── example 2.png
│ │ ├── ezgif-242d06617aea38.gif
│ │ ├── Feature Tab-min.png
│ │ ├── Feature targeting rules example v2-min.png
│ │ ├── Feature targeting rules example V2-min.png
│ │ ├── Feature targeting rules example v3-min.png
│ │ ├── Feature targeting rules example-min.png
│ │ ├── Feature targeting rules UI V2-min.png
│ │ ├── Feature targeting rules UI v3-min.png
│ │ ├── Feature targeting rules UI-min.png
│ │ ├── Feature usage configuration-v2-min.png
│ │ ├── Feature view.png
│ │ ├── feature-flag-list-rum-event.d9c1c876a34458edc70d1317efaec05b.png.avif
│ │ ├── Feature-targeting-rules-v2-min.png
│ │ ├── Features Page V2-min (1).png
│ │ ├── Features Page V2-min.png
│ │ ├── Features Page-min.png
│ │ ├── Features-min.png
│ │ ├── Feedback Tab V2-min.png
│ │ ├── Feedback-min.png
│ │ ├── Getting started-min.png
│ │ ├── gitbook-logo.svg
│ │ ├── github-logo.svg
│ │ ├── Global settings - Feature views-min.png
│ │ ├── Global settings - Manual Targeting-min.png
│ │ ├── Global settings - Release Stages Editing V4-min.png
│ │ ├── Global settings - Release Stages-min.png
│ │ ├── Goal Form.png
│ │ ├── How to use release stages v2-min.png
│ │ ├── How to use release stages-min (1).png
│ │ ├── How to use release stages-min.png
│ │ ├── https___content.gitbook.com_content_pgXAy2Cgsm5pON9oJ06m_blobs_6wGbrQlJPE4JllBuIhla_image (1).png
│ │ ├── image (1) (1).png
│ │ ├── image (1) (2).png
│ │ ├── image (1).png
│ │ ├── image (10).png
│ │ ├── image (11).png
│ │ ├── image (12).png
│ │ ├── image (13).png
│ │ ├── image (14).png
│ │ ├── image (15).png
│ │ ├── image (16).png
│ │ ├── image (17).png
│ │ ├── image (18).png
│ │ ├── image (19).png
│ │ ├── image (2) (1).png
│ │ ├── image (2).png
│ │ ├── image (20).png
│ │ ├── image (21).png
│ │ ├── image (22).png
│ │ ├── image (23).png
│ │ ├── image (24).png
│ │ ├── image (25).png
│ │ ├── image (26).png
│ │ ├── image (27).png
│ │ ├── image (28).png
│ │ ├── image (29).png
│ │ ├── image (3).png
│ │ ├── image (30).png
│ │ ├── image (31).png
│ │ ├── image (32).png
│ │ ├── image (33).png
│ │ ├── image (4).png
│ │ ├── image (5).png
│ │ ├── image (6).png
│ │ ├── image (7).png
│ │ ├── image (8).png
│ │ ├── image (9).png
│ │ ├── image.png
│ │ ├── Iterate Feature V2.png
│ │ ├── LInear mention.mp4
│ │ ├── linear.svg
│ │ ├── mcp-remote-min.mp4
│ │ ├── mcp-remote.mp4
│ │ ├── mixpanel.svg
│ │ ├── Modifying or deleting an app-min.png
│ │ ├── Monitor (1) (1).png
│ │ ├── Monitor (1).png
│ │ ├── Monitor (2).png
│ │ ├── Monitor (3).png
│ │ ├── Monitor (4).png
│ │ ├── Monitor (5).png
│ │ ├── Monitor (6).png
│ │ ├── Monitor (7).png
│ │ ├── Monitor.png
│ │ ├── New feature.png
│ │ ├── next-js.svg
│ │ ├── node-js.svg
│ │ ├── openfeature.svg
│ │ ├── posthog.svg
│ │ ├── Pre-Release.png
│ │ ├── react.svg
│ │ ├── Release Goals.png
│ │ ├── Release Stage Beta Targeting Rules v3-min.png
│ │ ├── Release Stage Beta Targeting Rules V3-min.png
│ │ ├── Release Stage Beta Targeting Rules V5-min.png
│ │ ├── Release Stage Beta Targeting Rules-min.png
│ │ ├── remote config - 3.png
│ │ ├── Remote config.png
│ │ ├── Rolling back flags-V2.png
│ │ ├── Rules in other environments.png
│ │ ├── rum-explorer-error-feature-flag-search.7b9f6c046db1de1c71d279c139f1508a.png.avif
│ │ ├── rum-explorer-session-feature-flag-search.435802460fd607608ad5155f029da57b.png.avif
│ │ ├── Satisfaction feedback-min.png
│ │ ├── Satisified-min.png
│ │ ├── Save the segment-min.png
│ │ ├── Saving New Segment-min.png
│ │ ├── Screenshot 2024-08-14 at 19.25.06 (1).png
│ │ ├── Screenshot 2024-08-14 at 19.25.06.png
│ │ ├── Screenshot 2024-08-15 at 13.57.46.png
│ │ ├── Screenshot 2024-10-10 at 14.04.09.png
│ │ ├── Screenshot 2024-10-10 at 14.04.34.png
│ │ ├── Screenshot 2025-07-10 at 14.04.07.png
│ │ ├── Screenshot 2025-07-10 at 14.11.01.png
│ │ ├── Screenshot 2025-07-10 at 14.29.20.png
│ │ ├── Screenshot 2025-07-15 at 21.31.16.png
│ │ ├── Screenshot 2025-07-21 at 20.07.27.png
│ │ ├── Screenshot 2025-09-02 at 17.08.25.png
│ │ ├── Screenshot 2025-09-02 at 17.10.36 (1).png
│ │ ├── Screenshot 2025-09-02 at 17.10.36 (2).png
│ │ ├── Screenshot 2025-09-02 at 17.10.36.png
│ │ ├── Screenshot 2025-09-02 at 17.11.21 (1).png
│ │ ├── Screenshot 2025-09-02 at 17.11.21.png
│ │ ├── Screenshot 2025-09-02 at 17.13.15 (1).png
│ │ ├── Screenshot 2025-09-02 at 17.13.15.png
│ │ ├── Screenshot 2025-09-02 at 17.19.44 (1).png
│ │ ├── Screenshot 2025-09-02 at 17.19.44.png
│ │ ├── Screenshot 2025-09-09 at 09.32.31.png
│ │ ├── Screenshot 2025-09-12 at 11.50.41.png
│ │ ├── Screenshot 2025-09-12 at 12.30.38.png
│ │ ├── Screenshot 2025-09-12 at 13.14.44.png
│ │ ├── Screenshot 2025-09-12 at 13.18.07.png
│ │ ├── Screenshot 2025-09-12 at 13.21.25.png
│ │ ├── Screenshot 2025-09-12 at 13.25.21.png
│ │ ├── Screenshot 2025-09-12 at 14.29.56.png
│ │ ├── Screenshot 2025-09-12 at 14.37.52.png
│ │ ├── Screenshot 2025-09-12 at 14.58.27.png
│ │ ├── Screenshot 2025-09-12 at 15.00.32.png
│ │ ├── Screenshot 2025-09-12 at 15.01.32.png
│ │ ├── Screenshot 2025-09-12 at 15.03.33.png
│ │ ├── Screenshot 2025-09-12 at 15.04.39.png
│ │ ├── Screenshot 2025-09-12 at 15.06.50.png
│ │ ├── Screenshot 2025-09-12 at 15.13.45.png
│ │ ├── Screenshot 2025-09-12 at 15.14.43.png
│ │ ├── Screenshot 2025-09-12 at 15.16.42.png
│ │ ├── Screenshot 2025-09-12 at 15.18.42.png
│ │ ├── Screenshot 2025-09-12 at 15.32.39.png
│ │ ├── Screenshot 2025-09-12 at 15.33.57.png
│ │ ├── Screenshot 2025-09-12 at 15.35.09.png
│ │ ├── Screenshot 2025-09-12 at 15.36.14.png
│ │ ├── segment (1).svg
│ │ ├── segment.svg
│ │ ├── Segments.png
│ │ ├── Set segment conditions-min.png
│ │ ├── Setting multiple targeting rules.png
│ │ ├── Setting Tab-min.png
│ │ ├── Setting targeting rules v3-min.png
│ │ ├── Setting targeting rules-min.png
│ │ ├── Settings-min (1).png
│ │ ├── Settings-min.png
│ │ ├── slack (1).svg
│ │ ├── Slack (with auto-layout)-min.png
│ │ ├── Slack and Environments-min.png
│ │ ├── Slack and Feature views-min.png
│ │ ├── Slack Integration.png
│ │ ├── Slack Settings under Features-min.png
│ │ ├── Slack with User Feedback.png
│ │ ├── slack.svg
│ │ ├── slackConnected (1).png
│ │ ├── slackConnected.png
│ │ ├── slackDisconnected (1).png
│ │ ├── slackDisconnected.png
│ │ ├── STARS Configuration-min.png
│ │ ├── STARS Feature Funnel-min.png
│ │ ├── STARS Feature Report-min.png
│ │ ├── STARS states.png
│ │ ├── surveys-min.png
│ │ ├── Switching Between Environments-min.png
│ │ ├── Targeting rules interface-min.png
│ │ ├── Targeting rules.png
│ │ ├── There are 5 different types of conditions to chose from-min.png
│ │ ├── Track adoption in the UI V2-min.png
│ │ ├── Track adoption in the UI v3-min.png
│ │ ├── Track adoption in the UI-min.png
│ │ ├── Track new feature V2-min.png
│ │ ├── Tracking Tab-min.png
│ │ ├── ts-js.svg
│ │ ├── type-check-failed.png
│ │ ├── type-check-payload-failed.png
│ │ ├── usage attribute example v3.png
│ │ ├── usage attribute example-min.png
│ │ ├── Usage configuration-min.png
│ │ ├── vercel-logo.svg
│ │ ├── vue-logo.svg
│ │ ├── What is the STARS Framework v3-min.png
│ │ └── What is the STARS Framework_-min.png
│ └── includes
│ ├── integrations.md
│ ├── languages.md
│ ├── need-some-help-chat-with-us.md
│ ├── sdks.md
│ └── untitled.md
├── .github
│ └── README.md
├── .vscode
│ └── settings.json
├── api
│ ├── api-access.md
│ ├── cli.md
│ ├── mcp.md
│ ├── public-api
│ │ ├── public-api-reference.md
│ │ └── README.md
│ └── reflag-rest-api
│ ├── README.md
│ └── reflag-api-reference.md
├── guides
│ ├── self-opt-in.md
│ └── use-reflag-in-your-cli.md
├── integrations
│ ├── amplitude.md
│ ├── aws-s3.md
│ ├── cursor.md
│ ├── datadog.md
│ ├── github.md
│ ├── linear.md
│ ├── mixpanel.md
│ ├── overview.md
│ ├── posthog.md
│ ├── segment.md
│ └── slack.md
├── introduction
│ └── concepts
│ ├── app.md
│ ├── company.md
│ ├── environment.md
│ ├── event.md
│ ├── feature-events.md
│ ├── feature-view.md
│ ├── feature.md
│ ├── feedback.md
│ ├── filter.md
│ ├── README.md
│ ├── release-stage.md
│ ├── segment.md
│ ├── targeting-rules.md
│ └── user.md
├── product-handbook
│ ├── anonymous-users.md
│ ├── concepts
│ │ ├── app.md
│ │ ├── company.md
│ │ ├── environment.md
│ │ ├── event.md
│ │ ├── feature-events.md
│ │ ├── feature-view.md
│ │ ├── feature.md
│ │ ├── feedback.md
│ │ ├── filter.md
│ │ ├── README.md
│ │ ├── release-stage.md
│ │ ├── segment.md
│ │ ├── targeting-rules.md
│ │ └── user.md
│ ├── creating-and-managing-apps
│ │ ├── environments.md
│ │ └── README.md
│ ├── creating-and-managing-apps.md
│ ├── creating-segments.md
│ ├── data-export.md
│ ├── data-residency.md
│ ├── feature-clean-up-and-archival-beta
│ │ ├── ai-code-clean-up-beta.md
│ │ └── README.md
│ ├── feature-entitlements
│ │ ├── README.md
│ │ └── simple-role-based-entitlements.md
│ ├── feature-rollouts
│ │ ├── feature-targeting-rules.md
│ │ └── README.md
│ ├── feature-targeting-rules
│ │ ├── creating-segments.md
│ │ └── environments.md
│ ├── feature-views.md
│ ├── launch-monitor
│ │ ├── automated-feedback-surveys.md
│ │ ├── give-feedback-button.md
│ │ └── README.md
│ ├── product-overview.md
│ ├── remote-config.md
│ ├── self-opt-in.md
│ ├── service-resiliency.md
│ ├── team-permissions.md
│ └── type-safety.md
├── README.md
├── sdk
│ ├── _media
│ │ ├── type-check-failed.png
│ │ └── type-check-payload-failed.png
│ ├── @reflag
│ │ ├── browser-sdk
│ │ │ ├── globals.md
│ │ │ └── README.md
│ │ ├── node-sdk
│ │ │ ├── globals.md
│ │ │ └── README.md
│ │ ├── react-sdk
│ │ │ ├── globals.md
│ │ │ └── README.md
│ │ └── vue-sdk
│ │ ├── globals.md
│ │ └── README.md
│ ├── documents
│ │ ├── browser-sdk
│ │ │ └── FEEDBACK.md
│ │ └── cli
│ │ └── README.md
│ └── README.md
├── SUMMARY.md
├── support
│ └── get-support.md
└── supported-languages
├── next.js.md
├── openfeature.md
├── overview.md
└── ruby-rails-stimulus.md
```
# Files
--------------------------------------------------------------------------------
/introduction/concepts/README.md:
--------------------------------------------------------------------------------
```markdown
# Data model
```
--------------------------------------------------------------------------------
/product-handbook/concepts/README.md:
--------------------------------------------------------------------------------
```markdown
# Data model
```
--------------------------------------------------------------------------------
/product-handbook/creating-and-managing-apps/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about apps in Reflag
---
# Managing apps
Learn about [apps](../concepts/app.md) here.
### Modifying or deleting an app
* On the sidebar, click `Settings`
* Under the `App:[App Name]` heading, click `General`
* You can modify the `App name`
* You can delete the app by clicking the `Delete app` button
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.32.39.png" alt="Reflag Global Settings page"><figcaption></figcaption></figure>
### Creating a new app
If you have multiple products or applications, you can create additional apps.
* Click on `[Current app name]`, found in the top-left corner
* In the tab that appears, click `New app`
* Name the app and click `Create`
```
--------------------------------------------------------------------------------
/sdk/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Documentation
## Documents
<table>
<thead>
<tr>
<th>Document</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
[browser-sdk/FEEDBACK](documents/browser-sdk/FEEDBACK.md)
</td>
<td>
‐
</td>
</tr>
<tr>
<td>
[cli/README](documents/cli/README.md)
</td>
<td>
‐
</td>
</tr>
</tbody>
</table>
## Packages
<table>
<thead>
<tr>
<th>Package</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
[@reflag/browser-sdk](@reflag/browser-sdk/README.md)
</td>
<td>
‐
</td>
</tr>
<tr>
<td>
[@reflag/node-sdk](@reflag/node-sdk/README.md)
</td>
<td>
‐
</td>
</tr>
<tr>
<td>
[@reflag/react-sdk](@reflag/react-sdk/README.md)
</td>
<td>
‐
</td>
</tr>
<tr>
<td>
[@reflag/vue-sdk](@reflag/vue-sdk/README.md)
</td>
<td>
‐
</td>
</tr>
</tbody>
</table>
```
--------------------------------------------------------------------------------
/.github/README.md:
--------------------------------------------------------------------------------
```markdown
<img width="1200" alt="reflag-docs-og" src="https://docs.reflag.com/~gitbook/image?url=https%3A%2F%2F412612722-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Forganizations%252FDu9vflR1aVGOJElT6Sip%252Fsites%252Fsite_RVvaB%252Fsocialpreview%252FQMZvELgHSV06HcHke0HB%252FOG%2520-%2520Docs.jpg%3Falt%3Dmedia%26token%3Dd3b36bf6-20da-475c-84c9-9ae887b7a15d&width=1200&height=630&sign=6f89fdbf&sv=2" />
<br> Welcome to Reflag, a feature flag provider crafted for SaaS companies.
Reflag is built to work at the company/organization level right out of the box, is quickly set up, and gives you feature adoption metrics and customer feedback in a beautifully crafted UI.
**Key features**
- **Feature flags for B2B**: company-level targeting rules, user aggregation, filtering, segments, and reporting
- **Feature entitlements**: grant companies access by flipping a switch
- **Feature remote config**: manage feature configuration with ease in one place
- **Feature adoption metrics**: using a proven and B2B-optimized framework
- **Feature feedback**: using surveys or feedback buttons
- **Feature data export**: sync with your CRM and/or data warehouse
**About**
This repository syncs the documentation to [docs.reflag.com](https://docs.reflag.com). For SDK docs, please go to the [javascript repository](https://github.com/reflagcom/javascript) repository.
## Quick links
- Ready to get started? [Follow the guide](https://docs.reflag.com/introduction/getting-started)
- Need help? [Talk to a founder](https://reflag.com/contact)
- Latest product updates? [See Changelog](https://reflag.com/changelog)
Follow us [@bucketdotco on X](https://x.com/bucketdotco) or [@bucket.co on Bluesky](https://bsky.app/profile/bucket.co) for the latest product updates.
We're crafting a feature flag management tool for B2B SaaS.
```
--------------------------------------------------------------------------------
/product-handbook/launch-monitor/README.md:
--------------------------------------------------------------------------------
```markdown
# Launch monitor
Use the launch monitor to track exposure and adoption, and to collect end-user feedback.
<figure><img src="../../.gitbook/assets/Monitor (7).png" alt=""><figcaption></figcaption></figure>
## Exposure
The Exposed chart shows you the distinct count of companies that have been exposed the the feature. Exposed means that they've been checked for feature access in the SDK and the check returned `enabled`.
## Adoption
The Tracked chart shows you the dinstinct count of companies that have interacted with the feature. Interactions are tracked with the `track` method. Here's a code example:
```typescript
import { useFlag } from "@reflag/react-sdk";
function StartHuddleButton() {
const { isLoading, isEnabled, track } = useFlag("huddle");
if (isLoading) {
return <Loading />;
}
if (!isEnabled) {
return null;
}
return (
<div>
Huddles
<button onClick={() => track()}>Start huddle</button>
</div>
);
}
```
## Feedback
You can collect end-user feedback on new feature releases to catch and fix issues faster.
### Static feedback button
Here's a brief example using the [Reflag React SDK](../../sdk/@reflag/browser-sdk/) to collect feedback:
```tsx
import { useFlag } from "@reflag/react-sdk";
function StartHuddleButton() {
const { isLoading, isEnabled, requestFeedback } = useFlag("my-feature");
if (isLoading) {
return <Loading />;
}
if (!isEnabled) {
return null;
}
return (
<>
<button>Use feature!</button>
<button
onClick={() => requestFeedback({ title: "How do you like <feature>?" })}
>
Give feedback!
</button>
</>
);
}
```
### Automated feedback survey
Automated surveys lets you ask for feedback at just the right time after N interactions with the feature. [Learn more here](automated-feedback-surveys.md).
```
--------------------------------------------------------------------------------
/product-handbook/feature-clean-up-and-archival-beta/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
Managing feature flag lifecycle on Reflag is straight forward with the
"clean-up guide", notifications and automatic clean-up pull requests.
---
# Feature clean-up and archival
## Stale features
After features have been rolled out to everyone, they turn stale after a given period of time. Stale features show up with a little broom next to their name and you also receive a Slack notification if the Slack notification is enabled
<figure><img src="../../.gitbook/assets/Screenshot 2025-07-15 at 21.31.16.png" alt=""><figcaption></figcaption></figure>
## Stale features view
The stale features view lets you see all the features that are currently stale as well as what needs to be done before they can be archived
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-02 at 17.19.44 (1).png" alt=""><figcaption></figcaption></figure>
## Clean-up guide
Open up a feature and find the built in "Clean-up guide". The "Clean-up guide" helps you through the steps required to safely archive a feature.
<figure><img src="../../.gitbook/assets/Screenshot 2025-07-10 at 14.04.07.png" alt="" width="563"><figcaption></figcaption></figure>
There are three **checks** that must pass for the feature to be safe to archive:
* Stale: Feature was rolled out to everyone some time ago
* Flag removed from the code in a GitHub repository
* No access checks for some time
There are two **automations** that can be enabled at the feature level:
* Auto-creating a Pull Request once the feature turns stale
* Auto-archiving once all checks pass
See the [AI code clean-up](ai-code-clean-up-beta.md) page for more information on automating code clean-up
## Organization clean-up settings
In organization settings, you control requirements for each checks to pass:
* Configure how soon after rollout features should be considered stale
* If GitHub is connected, you'll see which repository will be checked for the presence of flags
* How long to wait for the last access check
You can also set the default automation settings for newly created features.
<figure><img src="../../.gitbook/assets/Screenshot 2025-07-10 at 14.11.01.png" alt=""><figcaption></figcaption></figure>
```
--------------------------------------------------------------------------------
/api/reflag-rest-api/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: Introduction to Reflag REST API
---
# Reflag REST API
## What is the REST API?
The Reflag REST API allows developers to programmatically interact with their Reflag accounts. 
By using HTTP requests, such as GET, POST, PUT, and DELETE, users can perform actions like retrieving data, updating account settings, or managing resources without accessing the Reflag web application directly. This enables seamless integration with other systems, automation of tasks, and enhanced flexibility in account management.
{% hint style="info" %}
The Reflag REST API serves a different purpose than the Public API. For app integrations, please use the [Public API](../public-api/).
{% endhint %}
## Authentication
To begin, generate a new [API key](../api-access.md) from your Reflag app settings. An API key is associated with a specific app and is usable across all environments. It comes with designated scopes that define its capabilities.
Pass the API keys to Reflag API through the `Authorization` header using the `bearer` scheme.
## Use Cases
This section covers a few simple use cases for the Reflag REST API.
### Toggling Flags
The REST API enables customers to integrate their back-office systems with Reflag's flag targeting. By using our API, you can quickly provide access to specific flags for a company or user directly from your systems.
Here's a brief guide to enabling the `new-checkout-flow` flag for the `acme-corp` company:
```typescript
await fetch(
`https://app.reflag.com/api/apps/${appId}/flags/specific-targets/${envId}`,
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiToken}`,
},
body: JSON.stringify({
updates: [
{
flagKey: "new-checkout-flow",
value: true,
companyId: "acme-corp",
},
],
changeDescription: "Enabled new checkout flow for Acme Corp in prod",
}),
}
);
```
#### Automating TypeScript Type Generation with Reflag CLI in CI/CD
To automate TypeScript type generation in your CI/CD pipeline, use the Reflag CLI.
1. First, ensure the Reflag CLI is installed and set up in your project.
2. Second, store the API key in the environment (e.g, action secrets within GitHub).
To use the tool in your CI/CD pipeline, simply invoke it as follows:
```sh
# Invoke directly if the environment contains the REFLAG_API_KEY:
npx reflag flags types
# Manually specify the key if not in the environment or using a different name:
npx reflag flags types --api-key ${REFLAG_CI_KEY}
```
## Further Documentation <a href="#install-the-sdk" id="install-the-sdk"></a>
For a comprehensive overview of the available Reflag REST API endpoints, refer to the [API Reference](reflag-api-reference.md) section.
```
--------------------------------------------------------------------------------
/product-handbook/feature-rollouts/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about feature rollouts in Reflag
---
# Feature rollouts
You release features gradually to de-risk rollouts. It's better that only a few beta accounts encounter bugs rather than the entire user base.
Ideally, you first test internally and then roll out a limited release to beta customers. Once you've caught the major bugs or points of confusion, you release the feature to general availability.
## Gradually roll out your feature
To roll out a feature in Reflag, you can set access rules.
## Setting access rules
[Access rules](feature-targeting-rules.md) on Reflag are designed to simplify the rollout process in B2B companies.
The default access criteria are:
* Company segments
* Companies
* Users
These criteria let you add segments, companies, or users without additional configuration.
If you'd like to specify a [rollout percentage](feature-targeting-rules.md#specify-rollout-percentage) or create [advanced access rules](feature-targeting-rules.md#advanced-targeting-rules) using company attributes, user attributes, feature access, or other contexts, you can add additional access rules with the "+ Add rule" button.
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 13.14.44.png" alt="Setting targeting rules in Reflag"><figcaption></figcaption></figure>
## Using release stages
Release stages let you easily signal features' rollout progress to your team and, optionally, set access rules for each stage of the rollout process.
Release stages are designed to support the common use case of taking a feature from development to internal testing to a beta testing phase, then finally released to everyone.
New apps come with 4 default release stages: In development, Internal, Beta, and General availability.
{% hint style="info" %}
Release stages are fully customizable. Go the the [Release stages settings](https://app.reflag.com/env-current/settings/app-stages) to adopt them to your needs.
{% endhint %}
#### **In development**
When you create a new feature, it is placed in the "In development" stage by default. This release stage signals that a feature is currently being built.
#### **Internal**
The "Internal" stage signals a feature is ready for internal QA testing.
#### **Beta**
After internal QA testing is complete, a feature can be moved to the "Beta" stage. This stage signals that a feature is ready to be tested by a limited segment of users.
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 13.18.07.png" alt="Targeting rules in the Reflag UI"><figcaption></figcaption></figure>
#### **General availability**
After rolling out a feature to your beta users and making any fixes, you can move to the "General availability" stage. This stage signals that a feature is now live to your general user base.
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# Getting started
**Welcome!** Let's get started. We'll do the following:
1. Create your first feature flag.
2. Install the Reflag SDK.
3. Set feature access rules and/or remote configuration.
4. Enable Toolbar for local testing
5. Monitor your feature launch.
## 1. Create your first flag
Now let's create your first flag.
{% tabs %}
{% tab title="CLI" %}
```
npx @reflag/cli new
```
See [CLI docs](sdk/documents/cli/).
{% endtab %}
{% tab title="UI" %}
1. [Sign up](https://app.reflag.com/) in the app
2. Click `New flag` in the sidebar.
3. Give your feature a name, and we'll suggest a `flag key` .
<figure><img src=".gitbook/assets/Screenshot 2025-09-12 at 11.50.41.png" alt=""><figcaption></figcaption></figure>
{% endtab %}
{% tab title="MCP" %}
You can create features from your code editor via our [MCP](api/mcp.md).
{% endtab %}
{% tab title="Linear" %}
You can create features from within Linear by mentioning the `@reflag` [agent](integrations/linear.md).
{% endtab %}
{% endtabs %}
Next, let's set up a Reflag SDK for your language and framework.
## 2. Install the Reflag SDK
Find the supported languages below:
{% include ".gitbook/includes/sdks.md" %}
### Code example for React
If you've installed the React SDK and have created a feature called `my-new-feature`, getting started will look like the following:
```jsx
import { useFlag } from "@reflag/react-sdk";
const MyFeature = () => {
const { isEnabled } = useFlag("my-new-feature");
return isEnabled ? "You have access!" : null;
};
```
You can now use `isEnabled` to gate access to the feature.
## 3. Set access rules
Head back over to [your dashboard](https://app.reflag.com/), select your feature and the `Access` tab.
<figure><img src=".gitbook/assets/Access.png" alt=""><figcaption></figcaption></figure>
From here, you can define segments, companies, and users that will access your feature.
## 4. Enable Toolbar for local testing <a href="#next-steps-1" id="next-steps-1"></a>
In the frontend SDK, enable the Toolbar to toggle features locally. 
<figure><img src=".gitbook/assets/CleanShot 2025-10-09 at 10 [email protected]" alt=""><figcaption></figcaption></figure>
In the React SDK, you enable it with `toolbar:`
```jsx
<ReflagProvider
publishableKey=""
context={}
toolbar={true}
>
```
## 5. Monitor your feature launch <a href="#next-steps-1" id="next-steps-1"></a>
On the Monitor tab you can track real-time feature exposure, adoption and user feedback.
<figure><img src=".gitbook/assets/Monitor.png" alt=""><figcaption></figcaption></figure>
### Track exposure
The Exposed chart shows you companies that have been exposed to your feature. This means, companies that have been checked for feature access as per your targeting rules and the check return "enabled".
### Track adoption
To track if exposed companies are also interacting with your feature, you can use `track` .
See the code example below.
### Get user feedback
To get feedback from your users, you can add a [static "Feedback" button](product-handbook/launch-monitor/#static-feedback-button) or you can [trigger a survey](product-handbook/launch-monitor/automated-feedback-surveys.md), at the right time.
Here's an example with a static feedback button.
```tsx
import { useFlag } from "@reflag/react-sdk";
const MyFeature = () => {
const { isEnabled, requestFeedback } = useFlag("my-new-feature");
if (!isEnabled) {
return null;
}
return (
<>
<button onClick={() => track()}>Use feature</button>
<button
onClick={() => requestFeedback({ title: "How do you like this new feature?" })}
>
Give feedback
</button>
</>
);
}
```
## Get support
* Need some help? [Chat with us](mailto:[email protected])
* Latest product updates? [See Changelog](https://reflag.com/changelog)
* Create account: [Sign up](https://app.reflag.com/)
```
--------------------------------------------------------------------------------
/product-handbook/feature-entitlements/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about feature entitlements in Reflag
---
# Feature entitlements
In B2B SaaS, a typical use case is to manage feature access based on the customer’s subscription level. This means enforcing feature access at the company level, not the user level. 
This is how Reflag is used to manage feature entitlements.
## Why use flags for this use case?
There are multiple ways to control feature access: You can hard-code it, use a dedicated billing service, or use feature flags.
If you have a complex billing structure, adding a dedicated service to your stack likely makes the most sense.
If your billing is relatively straightforward, you can use flags for it. This keeps the number of services to a minimum and lets you roll out new features and manage access from one interface.
However, not all flagging services are the same. Most are focused on end-users rather than company accounts. 
Reflag's feature flagging is purpose-built for B2B with native support for gating features at the company subscription level.
## Gate a feature based on subscription plan
### Step 1: Initialize Reflag
Choose [an SDK](broken-reference) to get started, if you haven't already. \
\
Reflag needs to know who the authenticated user is and which company they belong to. We attached attribute metadata, such as the company's subscription plan.
```tsx
// identify user
reflag.user(userId1356, {
name: “Rasmus Makwarth”,
});
// associate user with company
reflag.company(companyId51, {
name: “Acme Inc.”,
plan: “business”,
});
```
Reflag now understands that Rasmus works for Acme Inc. and Acme Inc. is on the Business subscription plan.
{% hint style="info" %}
You can send company attributes as part of the user sign-in event, via a nightly job, or use `updateCompany()` when the attribute value changes.
{% endhint %}
### Step 2: Group companies by plan
Next, we need to group companies on the "Business" subscription plan. 
We do this using segments. Segments let you group company accounts based on various filters, including company attributes like subscription plans.
In Reflag, segments are automatically aggregated at the company level. This means creating a segment for "Business" plan customers is as simple as: 
Company attribute **"plan**" equals **"business**"
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 14.58.27.png" alt=""><figcaption></figcaption></figure>
You can do this for all plans. For example:
* Starter
* Business
* Enterprise
### Step 3: Gate the feature
Let’s say you have an export feature that's only available to customers on the "Business" or "Enterprise" plans. To gate this feature with Reflag, you create a new feature called “Export to CSV”. A feature can be as small as a button or as big as a product area.
Each feature comes with a [feature key](../concepts/feature.md#feature-key), like `export-to-csv`, which you wrap your feature in inside your codebase. 
In React, it’d look like this:
```tsx
const { isEnabled } = useFlag("export-to-csv");
if(isEnabled) {
// access to csv export!
}
```
With the feature code in, you can now manage access to this feature via the Reflag UI. 
In this case, we’ll set the feature access rules to be: 
Companies in the segment **Business** or **Enterprise**
Here’s what that looks like in the Reflag UI:
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.00.32.png" alt=""><figcaption></figcaption></figure>
That’s it! 
Every time a company enters either of these segments, they’ll automatically get access to the "Export to CSV" feature. Similarly, if they downgrade, they lose access.
## Grant individual companies access
If you need to grant individual companies access to a feature when they don't have the required subscription plan, you can add them manually.
Simply click the "+ Add" button beside the "Companies" label and select the companies you'd like to add from the searchable dropdown.
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.01.32.png" alt=""><figcaption></figcaption></figure>
## How to handle usage-based gating
{% hint style="info" %}
This use case isn't yet natively supported by Reflag, but Reflag is flexible enough to handle it in some cases.
{% endhint %}
If your features are restricted by plan _and_ usage, like only allowing 1,000 API requests/mo on the Business plan, you can do the following:
### Step 1: Let Reflag know of the current usage 
Send usage metrics to Reflag using company attributes. 
For example, you can send the company's current usage metrics to Reflag at an hourly or daily interval.
```tsx
reflag.companyUpdate(companyId51, {
apiRequestsCurrentMonth: 793
});
```
### Step 2: Gate using usage attribute
Then, add this custom attribute metric to your access rules.
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.04.39.png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../.gitbook/assets/Screenshot 2025-09-12 at 15.06.50.png" alt=""><figcaption></figcaption></figure>
```
--------------------------------------------------------------------------------
/sdk/documents/cli/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Reflag CLI
Command-line interface for interacting with Reflag services. The CLI allows you to manage apps,
flags, authentication, and generate TypeScript types for your Reflag flags. With this tool,
you can streamline your flagging workflow directly from your terminal.
## Installation
Install the CLI as a development dependency in your project:
```bash
# npm
npm install --save-dev @reflag/cli
# yarn
yarn add --dev @reflag/cli
```
Run the `new` command from your project's root directory to initialize the CLI, create a flag, and generate TypeScript types in one step:
```bash
# npm
npx reflag new
# yarn
yarn reflag new
```
## Migrating from Bucket SDK
If you're migrating from the Bucket CLI, here are the key changes to be aware of:
- **Command name**: Changed from `bucket` to `reflag`
- **Type definitions file**: Renamed from `features.d.ts` to `flags.d.ts` (manually remove the old file if it was committed)
- **Authentication file**: Changed from `.bucket-auth` to `.reflag-auth` (rename or remove the old file)
- **Configuration file**: Changed from `bucket.config.json` to `reflag.config.json` (rename or remove the old file)
- **Command**: `features` command is now `flags`
- **Environment variable**: Use `REFLAG_API_KEY` instead of `BUCKET_API_KEY`
**Important**: Update your scripts, build steps, and `.gitignore` patterns to reflect these changes.
### Individual Commands
For more control, you can run each command individually:
```bash
# Initialize Reflag in your project (if not already setup)
npx reflag init
# Create a new flag
npx reflag flags create "My Flag"
# Generate TypeScript types for your flags
npx reflag flags types
```
## Configuration
The CLI creates a `reflag.config.json` file in your project directory when you run `reflag init`. This file contains all the necessary settings for your Reflag integration.
### Configuration File Structure
Here are all the configuration options available in the `reflag.config.json` file:
```json
{
"$schema": "https://unpkg.com/@reflag/cli@latest/schema.json",
"baseUrl": "https://app.reflag.com",
"apiUrl": "https://app.reflag.com/api",
"appId": "ap123456789",
"typesOutput": [
{
"path": "gen/flags.d.ts",
"format": "react"
}
]
}
```
| Option | Description | Default |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| `$schema` | Autocompletion for the config. `latest` can be replaced with a specific version. | "https://unpkg.com/@reflag/cli@latest/schema.json" |
| `baseUrl` | Base URL for Reflag services. | "https://app.reflag.com" |
| `apiUrl` | API URL for Reflag services (overrides baseUrl for API calls). | "https://app.reflag.com/api" |
| `appId` | Your Reflag application ID. | Required |
| `typesOutput` | Path(s) where TypeScript types will be generated. Can be a string or an array of objects with `path` and `format` properties. Available formats: `react` and `node`. | "gen/flags.ts" with format "react" |
You can override these settings using command-line options for individual commands.
## Commands
### `reflag init`
Initialize a new Reflag configuration in your project. This creates a `reflag.config.json` file with your settings and prompts for any required information not provided via options.
```bash
npx reflag init [--overwrite]
```
Options:
- `--overwrite`: Overwrite existing configuration file if one exists.
- `--app-id <id>`: Set the application ID.
- `--key-format <format>`: Set the key format for flags.
### `reflag new [flagName]`
All-in-one command to get started quickly. This command combines `init`, flag creation, and type generation in a single step. Use this for the fastest way to get up and running with Reflag.
```bash
npx reflag new "My Flag" [--app-id ap123456789] [--key my-flag] [--key-format custom] [--out gen/flags.ts] [--format react]
```
Options:
- `--key`: Specific key for the flag.
- `--app-id`: App ID to use.
- `--key-format`: Format for flag keys (custom, snake, camel, etc.).
- `--out`: Path to generate TypeScript types.
- `--format`: Format of the generated types (react or node).
If you prefer more control over each step, you can use the individual commands (`init`, `flags create`, `flags types`) instead.
### `reflag login`
Authenticate with your Reflag account. This stores your credentials securely for subsequent operations.
```bash
npx reflag login
```
### `reflag logout`
Sign out from your Reflag account and remove stored credentials.
```bash
npx reflag logout
```
### `reflag flags`
Manage your Reflag flags with these subcommands:
#### `reflag flags create [flagName]`
Create a new flag in your Reflag app. The command guides you through the flag creation process with interactive prompts if options are not provided.
```bash
npx reflag flags create "My Flag" [--app-id ap123456789] [--key my-flag] [--key-format custom]
```
Options:
- `--key`: Specific key for the flag.
- `--app-id`: App ID to use.
- `--key-format`: Format for flag keys.
#### `reflag flags list`
List all flags for the current app. This helps you visualize what flags are available and their current configurations.
```bash
npx reflag flags list [--app-id ap123456789]
```
Options:
- `--app-id`: App ID to use.
#### `reflag flags types`
Generate TypeScript types for your flags. This ensures type safety when using Reflag flags in your TypeScript/JavaScript applications.
```bash
npx reflag flags types [--app-id ap123456789] [--out gen/flags.ts] [--format react]
```
Options:
- `--app-id`: App ID to use.
- `--out`: Path to generate TypeScript types.
- `--format`: Format of the generated types (react or node).
### `reflag apps`
Commands for managing Reflag apps.
## Global Options
These options can be used with any command:
- `--debug`: Enable debug mode for verbose output.
- `--base-url <url>`: Set the base URL for Reflag API.
- `--api-url <url>`: Set the API URL directly (overrides base URL).
- `--api-key <key>`: Reflag API key for non-interactive authentication.
- `--help`: Display help information for a command.
## AI-Assisted Development
Reflag provides powerful AI-assisted development capabilities through rules and Model Context Protocol (MCP). These features help your AI development tools better understand your flags and provide more accurate assistance.
### Reflag Rules (Recommended)
The `rules` command helps you set up AI-specific rules for your project. These rules enable AI tools to better understand how to work with Reflag flags and how they should be used in your codebase.
```bash
npx reflag rules [--format <cursor|copilot>] [--yes]
```
Options:
- `--format`: Format to add rules in:
- `cursor`: Adds rules to `.cursor/rules/reflag.mdc` for Cursor IDE integration.
- `copilot`: Adds rules to `.github/copilot-instructions.md` for GitHub Copilot integration.
- `--yes`: Skip confirmation prompts and overwrite existing files without asking.
This command adds rules to your project that provide AI tools with context about how to set up and use Reflag flags. For the copilot format, the rules are added to a dedicated section in the file, allowing you to maintain other copilot instructions alongside Reflag's rules.
## Model Context Protocol
The Model Context Protocol (MCP) is an open protocol that provides a standardized way to connect AI models to different data sources and tools. In the context of Reflag, MCP enables your code editor to understand your flags, their states, and their relationships within your codebase. This creates a seamless bridge between your flag management workflow and AI-powered development tools. The MCP server is hosted by Reflag, making it easy to get started.
_\*\*Note: The Reflag `mcp` CLI command was previously used for a \_local_ server. However, in recent versions of the Reflag CLI, the `mcp` command has been repurposed to help you connect to the new remote MCP server.\*\*\_
### Setting up MCP
The `mcp` command helps you configure your editor or AI client to connect with Reflag's remote MCP server. This allows your AI tools to understand your flags and provide more contextual assistance.
```bash
npx reflag mcp [--editor <editor>] [--scope <local|global>]
```
Options:
- `--editor`: The editor/client to configure:
- `cursor`: [Cursor IDE](https://www.cursor.com/)
- `vscode`: [Visual Studio Code](https://code.visualstudio.com/)
- `claude`: [Claude Desktop](https://claude.ai/download)
- `windsurf`: [Windsurf](https://windsurf.com/editor)
- `--scope`: Whether to configure settings globally or locally for the project.
The command will guide you through:
1. Selecting which editor/client to configure.
2. Choosing which Reflag app to connect to.
3. Deciding between global or project-local configuration.
4. Setting up the appropriate configuration file for your chosen editor .
_**Note: The setup uses [mcp-remote](https://github.com/geelen/mcp-remote) as a compatibility layer allowing the remote hosted Reflag MCP server to work with all editors/clients that support MCP STDIO servers. If your editor/client supports HTTP Streaming with OAuth you can connect to the Reflag MCP server directly.**_
## Using in CI/CD Pipelines (Beta)
The Reflag CLI is designed to work seamlessly in CI/CD pipelines. For automated environments where interactive login is not possible, use the `--api-key` option or specify the API key in the `REFLAG_API_KEY` environment variable.
```bash
# Generate types in CI/CD
npx reflag apps list --api-key $REFLAG_API_KEY
```
**Important restrictions:**
- When using `--api-key`, the `login` and `logout` commands are disabled
- API keys bypass all interactive authentication flows
- API keys are bound to one app only. Commands such as `apps list` will only return the bound app
- Store API keys securely using your CI/CD platform's secret management
Example CI workflow:
```yaml
# GitHub Actions example
- name: Generate types
run: npx reflag flags types --api-key ${{ secrets.REFLAG_API_KEY }}
# GitHub Actions example (using environment):
- name: Generate types (environment)
run: npx reflag flags types
env:
REFLAG_API_KEY: ${{ secrets.REFLAG_CI_API_KEY }}
```
## Development
```bash
# Build the CLI
yarn build
# Run the CLI locally
yarn reflag [command]
# Lint and format code
yarn lint
yarn format
```
## Requirements
- Node.js >=18.0.0
## License
> MIT License
> Copyright (c) 2025 Bucket ApS
```
--------------------------------------------------------------------------------
/api/public-api/README.md:
--------------------------------------------------------------------------------
```markdown
---
description: Introduction to Reflag Public API
---
# Public API
## What is the Public API?
Our public API utilizes JSON over HTTP, allowing both browsers and backend services to access flag data and share information, including companies, users, and events.
## Authentication
To start, you need to obtain either a [_publishable_ or _secret_ SDK key](../api-access.md) from within your Reflag app settings.
Publishable keys can be either passed in the `Authorization` header using the `bearer` scheme, or as a query parameter when calling our Public API. Secret keys, on the other hand, can only be passed in the `Authorization` header:
```
// using headers
Authorization: Bearer <secret_or_publishable_key>
// using query argument
GET /features/enabled?publishableKey=<publishable_key>
```
## Global Infrastructure
The Public API currently resides at: `https://front.reflag.com/` and `https://front-eu.reflag.com` 
Requests to the front-facing API are automatically routed to a data center near you and should thus have a relatively low latency regardless of where your customers are located.
{% hint style="info" %}
Contact us if your customers often experience latency over `100ms`. We're happy to help by establishing a closer point of presence.
{% endhint %}
{% hint style="warning" %}
Use `https://front-eu.reflag.com` to ensure your requests are processed by an EU-based server, addressing regulatory concerns.
{% endhint %}
## API Endpoints
This section provides a streamlined overview of the API endpoints available through Reflag. Each endpoint is listed with its requirement for either a publishable or secret key, and a brief description of its functionality.
<table data-full-width="false"><thead><tr><th width="266">Endpoint</th><th width="149" data-type="checkbox">Publishable Key</th><th width="121" data-type="checkbox">Secret key</th><th>Description</th></tr></thead><tbody><tr><td><code>GET /features</code></td><td>false</td><td>true</td><td>Retrieve <em>all</em> features with their respective access rules</td></tr><tr><td><code>GET /features/evaluated</code></td><td>true</td><td>true</td><td>Retrieve features that are evaluated for the provided user/company</td></tr><tr><td><code>GET /features/enabled</code></td><td>true</td><td>true</td><td>Retrieve features that are enabled for the provided user/company</td></tr><tr><td><code>POST /features/events</code></td><td>true</td><td>true</td><td>Send events related to feature access</td></tr><tr><td><code>POST /user</code></td><td>true</td><td>true</td><td>Update user in Reflag</td></tr><tr><td><code>POST /company</code></td><td>true</td><td>true</td><td>Update company in Reflag</td></tr><tr><td><code>POST /event</code></td><td>true</td><td>true</td><td>Send events related to feature usage or user actions</td></tr><tr><td><code>POST /bulk</code></td><td>true</td><td>true</td><td>Send multiple calls in bulk.</td></tr></tbody></table>
{% hint style="info" %}
To successfully make a POST request, ensure that the API receives data in JSON format. Set the `Content-Type` header to `application/json` for proper processing.
{% endhint %}
### `GET /features`
This endpoint provides a complete list of flags along with their targeting rules. It's particularly useful for backend SDKs that need to retrieve and evaluate these rules locally. This approach enables determining which flags to activate for a specific user or company, eliminating the need to repeatedly call the `features/enabled` endpoint for each user or company.
#### Example
{% code title="Request" %}
```http
GET /features
Authorization: Bearer <secret_key>
```
{% endcode %}
{% code title="Response" %}
```json
{
"success": true,
"features": [
{
"key": "huddle",
"targeting": {
"version": 42,
"rules": [
{
"filter": {
"type": "group",
"operator": "and",
"filters": [
{
"type": "context",
"field": "company.id",
"operator": "IS",
"values": ["acme_inc"],
},
{
"type": "rolloutPercentage",
"partialRolloutAttribute": "company.id",
"partialRolloutThreshold": 100000
}
]
}
}
]
}
}
]
}
```
{% endcode %}
### `GET /features/evaluated`
This endpoint retrieves a list of flag values evaluated for a particular user or company.
{% hint style="info" %}
The endpoint is a `GET` request to ensure that the request can be completed without a `CORS Preflight` request to reduce latency.
{% endhint %}
The context must be flattened and provided as query parameters. For instance, given the following nested object:
```typescript
{
company: {
id: 42,
},
user: {
id: 99,
},
}
```
It needs to be flattened out into the following form: `context.company.id=42&context.user.id=99` .
#### Example
<pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>GET https://front.reflag.com/features/enabled?context.company.id=42&context.user.id=99&publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
</strong></code></pre>
{% code title="Response" %}
```json
{
"success": true,
"features": {
"huddles": {
"isEnabled": true,
"key": "huddles",
"targetingVersion": 42
}
}
}
```
{% endcode %}
{% hint style="danger" %}
Reflag utilizes attributes from the `company` endpoint to identify which features are enabled for specific companies. Ensure all `company` attributes referenced in the `context` are also provided through the `company` endpoint.
{% endhint %}
### `GET /features/enabled`
This endpoint is similar to `features/evaluated` but only includes flags that have been evaluated as `true`.
### `POST /features/events`
This endpoint is designed to relay flag "check" events for various functions within the Reflag. Check events automatically generated by Reflag SDKs when user code checks if a specific flag is activated.
#### Example
<pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>POST https://front.reflag.com/features/events?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
</strong><strong>Content-Type: application/json
</strong><strong>
</strong><strong>{
</strong> "action": "evaluate",
"key": "feature1",
"targetingVersion": 42,
"evalContext": {
"user": { "id": "john_doe" }, "company": {"id": "acme_inc"}
},
"evalResult": false,
"evalRuleResults": [false, false],
"evalMissingFields": ["f1"],
}
</code></pre>
### `POST /user`
#### User Endpoint Documentation
This endpoint is designed to track individual users within your application. It will create a new user if one doesn't exist or update existing users if their IDs were previously recorded.
* **Unique ID**: Use a stable unique identifier, such as a database ID or a stable hash, to reference users.
* **User Attributes**: You can include additional attributes for the user.
{% hint style="info" %}
If a user isn't associated with a company, their events will not be taken into account by Reflag in certain situations (such as [Automatic Feedback Surveys](../../product-handbook/launch-monitor/automated-feedback-surveys.md)). See the `POST /company` endpoint for details.
{% endhint %}
#### Expected Body
<table><thead><tr><th width="377">Field</th><th width="126" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601</td></tr></tbody></table>
#### Example
<pre class="language-http" data-title="Request" data-overflow="wrap"><code class="lang-http"><strong>POST https://front.reflag.com/user?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
</strong><strong>Content-Type: application/json
</strong><strong>
</strong><strong>{
</strong> "userId": 1234567890,
"attributes": {
"name": "Rasmus Makwarth",
"custom_property": true,
"some_number": 12,
"role": "button-pusher"
}
}
</code></pre>
### `POST /company`
This endpoint is designed to track individual companies _(organizations)_ within your application. It will create a new company if one doesn't exist, or update existing companies if their IDs were previously recorded.
* **Unique ID**: Use a stable unique identifier, such as a database ID or a stable hash, to reference companies.
* **Company Attributes**: You can include additional attributes for the company.
* **User ID**: You can associate a user with a company by providing the `userId`. This is important as flags in Reflag look at company-level data.
#### Expected Body
<table><thead><tr><th width="358">Field</th><th width="133" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>companyId</td><td>true</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601 String</td></tr><tr><td>userId</td><td>false</td><td>String</td></tr></tbody></table>
#### Example
To monitor which companies have Slack enabled, set `has_slack_enabled: true` for the desired companies. Then, create a flag in Reflag that uses `has_slack_enabled` attribute in its targeting rules.
{% code title="Request" overflow="wrap" %}
```http
POST https://front.reflag.com/company?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
Content-Type: application/json
{
"companyId": 101112231415,
"attributes": {
"name": "Acme Corp",
"domain": "acmeinc.com",
"plan": "enterprise",
"monthly_spend": 99,
"createdAt": "2024-01-01T10:00:00Z"
},
"userId": 1234567890
}
```
{% endcode %}
### `POST /event`
In your application, events help you monitor user interactions. It's recommended to focus on a few essential features and those under development. To track an event, invoke this method during user interaction.
In general, event names match the keys associated with your flags, allowing Reflag to align these events with the specific flag guarding the triggered code. However, when needed, you can utilize custom events for more tailored workflows.
#### Request Body
<table><thead><tr><th width="422">Field</th><th width="141.5" data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>event</td><td>true</td><td>String</td></tr><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>companyId</td><td>false</td><td>String</td></tr><tr><td>attributes</td><td>false</td><td>Object</td></tr><tr><td>timestamp</td><td>false</td><td>ISO 8601</td></tr></tbody></table>
#### Example
{% code title="Request" overflow="wrap" %}
```http
POST https://front.reflag.com/event?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
Content-Type: application/json
{
"event": "Sent message",
"userId": 1234567890,
"attributes": {
"position": "popover",
"version": 3
},
}
```
{% endcode %}
### `POST Feedback`
Submit qualitative feedback on a specific feature to complement your quantitative metrics. Collect a 1-5 satisfaction score, qualitative feedback, or both.
#### Request Body
<table><thead><tr><th>Field</th><th data-type="checkbox">Required</th><th>Type</th></tr></thead><tbody><tr><td>featureId</td><td>true</td><td>String</td></tr><tr><td>userId</td><td>true</td><td>String</td></tr><tr><td>companyId</td><td>false</td><td>String</td></tr><tr><td>score</td><td>false</td><td>Number (1-5)</td></tr><tr><td>comment</td><td>false</td><td>String</td></tr></tbody></table>
{% hint style="info" %}
Submit at least one of the optional fields: `score` or `comment`. Feedback is invalid if neither of the two is provided.
{% endhint %}
#### Example
{% code title="Request" overflow="wrap" %}
```http
POST https://front.reflag.com/feedback?publishableKey=pub_prod_Cqx4DGo1lk3Lcct5NHLjWy
Content-Type: application/json
{
"key": "flag_key",
"userId": 1234567890,
"companyId": 101112231415,
"score": 4,
"comment": "It's pretty nice, but I expect slightly more to be fully satisfied"
}
```
{% endcode %}
## Responses
The API returns a `200` status code for successful calls and a `400` status code for errors, including invalid request bodies.
{% hint style="info" %}
When you encounter a `400` response code, it indicates an invalid request. The response body includes detailed information useful for debugging. Retry attempts are ineffective without troubleshooting first.
{% endhint %}
A `403` response indicates that the provided publishable or secret keys are invalid or not allowed with this endpoint.
If you encounter a `500` status code, retry the request. Sending events to Reflag might result in duplicate entries, but this is rare.
## Further Documentation <a href="#install-the-sdk" id="install-the-sdk"></a>
For a comprehensive overview of the available Public API endpoints, refer to the [API Reference](public-api-reference.md) section.
```
--------------------------------------------------------------------------------
/sdk/@reflag/vue-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Reflag Vue SDK (beta)
Vue client side library for [Reflag.com](https://reflag.com)
Reflag supports flag toggling, tracking flag usage, requesting feedback on features and remotely configuring flags.
The Reflag Vue SDK comes with the same built-in toolbar as the browser SDK which appears on `localhost` by default.
## Install
Install via npm:
```shell
npm i @reflag/vue-sdk
```
## Migrating from Bucket SDK
If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
- `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
- `Feature*` classes, and types have been renamed to `Feature*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
- All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
- The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
- `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
- The SDKs will not emit `evaluate` and `evaluate-config` events anymore
- The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead og `bucket-*`
- The `featuresUpdated` hook has been renamed to `flagsUpdated`
- The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
- `getFeature` method is an alias for `getFlag`
- `getFeatures` method is an alias for `getFlags`
- `featuresUpdated` hook is an alias for `flagsUpdated`
If you are running with strict Content Security Policies active on your website, you will need change them as follows:
- `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
Finally, if you have customized the look & feel of the Feedback component, update `--bucket-feedback-*` CSS classes to `--reflag-feedback-*`
## Get started
### 1. Add the `ReflagProvider` context provider
Add the `ReflagProvider` context provider to your application:
**Example:**
```vue
<script setup lang="ts">
import { ReflagProvider } from "@reflag/vue-sdk";
</script>
<ReflagProvider
:publishable-key="publishableKey"
:context="{
user: { id: 'user_123', name: 'John Doe', email: '[email protected]' },
company: { id: 'acme_inc', plan: 'pro' },
}"
>
<!-- your app -->
</ReflagProvider>
```
If using Nuxt, wrap `<ReflagProvider>` in `<ClientOnly>`. `<ReflagProvider>` only renders client-side currently.
### 2. Use `useFlag get flag status
```vue
<script setup lang="ts">
import { useFlag } from "@reflag/vue-sdk";
const { isEnabled } = useFlag("huddles");
</script>
<template>
<div v-if="isEnabled">
<button>Start huddles!</button>
</div>
</template>
```
See [useFlag()](#useflag) for a full example
## Setting context
Reflag determines which flags are active for a given `user`, `company`, or `other` context.
You can pass these to the `ReflagProvider` using the `context` prop.
### Using the `context` prop
```vue
<ReflagProvider
:publishable-key="publishableKey"
:context="{
user: { id: 'user_123', name: 'John Doe', email: '[email protected]' },
company: { id: 'acme_inc', plan: 'pro' },
other: { source: 'web' },
}"
>
<!-- your app -->
</ReflagProvider>
```
### Legacy individual props (deprecated)
For backward compatibility, you can still use individual props, but these are deprecated and will be removed in the next major version:
```vue
<ReflagProvider
:publishable-key="publishableKey"
:user="{ id: 'user_123', name: 'John Doe', email: '[email protected]' }"
:company="{ id: 'acme_inc', plan: 'pro' }"
:other-context="{ source: 'web' }"
>
<!-- your app -->
</ReflagProvider>
```
> [!Important]
> The `user`, `company`, and `otherContext` props are deprecated. Use the `context` prop instead, which provides the same functionality in a more structured way.
### Context requirements
If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
Attributes which are not properties of the `user` or `company` can be supplied using the `other` property.
Attributes cannot be nested (multiple levels) and must be either strings, numbers or booleans.
A number of special attributes exist:
- `name` -- display name for `user`/`company`,
- `email` -- the email of the user,
- `avatar` -- the URL for `user`/`company` avatar image.
To retrieve flags along with their targeting information, use `useFlag(key: string)` hook (described in a section below).
Note that accessing `isEnabled` on the object returned by `useFlag()` automatically
generates a `check` event.
## Remote config
Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
Similar to `isEnabled`, each flag accessed using the `useFlag()` hook, has a `config` property. This configuration is managed from within Reflag. It is managed similar to the way access to flags is managed, but instead of the
binary `isEnabled` you can have multiple configuration values which are given to different user/companies.
### Get started with Remote config
```ts
const {
isEnabled,
config: { key, payload },
} = useFlag("huddles");
// isEnabled: true,
// key: "gpt-3.5",
// payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
```
`key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
Note that, similar to `isEnabled`, accessing `config` on the object returned by `useFlag()` automatically
generates a `check` event.
## `<ReflagProvider>` component
The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts listening for automated feedback survey events. The component can be configured using a number of props:
- `publishableKey` is used to connect the provider to an _environment_ on Reflag. Find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag,
- `context`: An object containing `user`, `company`, and `other` properties that make up the evaluation context used to determine if a flag is enabled or not. `company` and `user` contexts are automatically transmitted to Reflag servers so the Reflag app can show you which companies have access to which flags etc.
- `company`, `user` and `otherContext` (deprecated): Individual props for context. These are deprecated in favor of the `context` prop and will be removed in the next major version.
> [!Note]
> If you specify `company` and/or `user` they must have at least the `id` property, otherwise they will be ignored in their entirety. You should also supply anything additional you want to be able to evaluate flag targeting against,
- `timeoutMs`: Timeout in milliseconds when fetching flags from the server,
- `staleWhileRevalidate`: If set to `true`, stale flags will be returned while refetching flags in the background,
- `expireTimeMs`: If set, flags will be cached between page loads for this duration (in milliseconds),
- `staleTimeMs`: Maximum time (in milliseconds) that stale flags will be returned if `staleWhileRevalidate` is true and new flags cannot be fetched.
- `enableTracking`: Set to `false` to stop sending tracking events and user/company updates to Reflag. Useful when you're impersonating a user (defaults to `true`),
- `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
- `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
- `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
- `debug`: Set to `true` to enable debug logging to the console,
- `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
- `feedback`: Optional configuration for feedback collection
### Loading states
ReflagProvider lets you define a template to be shown while ReflagProvider is initializing:
```vue
<template>
<ReflagProvider
:publishable-key="publishableKey"
:user="user"
:company="{ id: 'acme_inc', plan: 'pro' }"
>
<template #loading>Loading...</template>
<StartHuddlesButton />
</ReflagProvider>
</template>
```
If you want more control over loading screens, `useIsLoading()` returns a `Ref<boolean>` which you can use to customize the loading experience.
## `<ReflagBootstrappedProvider>` component
The `<ReflagBootstrappedProvider>` component is a specialized version of `ReflagProvider` designed for server-side rendering and preloaded flag scenarios. Instead of fetching flags on initialization, it uses pre-fetched flags, resulting in faster initial page loads and better SSR compatibility.
### Usage
```vue
<script setup lang="ts">
import { ReflagBootstrappedProvider } from "@reflag/vue-sdk";
// Pre-fetched flags (typically from your server/SSR layer)
const bootstrappedFlags = {
context: {
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
},
flags: {
huddles: {
isEnabled: true,
config: {
key: "enhanced",
payload: { maxParticipants: 50, videoQuality: "hd" },
},
},
},
};
</script>
<template>
<ReflagBootstrappedProvider
:publishable-key="publishableKey"
:flags="bootstrappedFlags"
>
<StartHuddlesButton />
</ReflagBootstrappedProvider>
</template>
```
### Getting bootstrapped flags
You'll typically generate the `bootstrappedFlags` object on your server using the Node.js SDK or by fetching from the Reflag API. Here's an example using the Node.js SDK:
```js
// server.js (Node.js/SSR)
import { ReflagClient } from "@reflag/node-sdk";
const client = new ReflagClient({
secretKey: "your-secret-key", // Use secret key on server
});
await client.initialize();
// Fetch flags for specific context
const context = {
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
};
const bootstrappedFlags = client.getFlagsForBootstrap(context);
// Pass to your Vue app
```
### ReflagBootstrappedProvider Props
`ReflagBootstrappedProvider` accepts all the same props as `ReflagProvider` except:
- `flags`: The pre-fetched flags object containing context and flag data
- All other props available in `ReflagProvider` are supported except `context`, `user`, `company`, and `otherContext` (which are extracted from `flags.context`)
If the `flags` prop is not provided or is undefined, the provider will not initialize the client and will render in a non-loading state.
## `<ReflagClientProvider>` component
The `<ReflagClientProvider>` is a lower-level component that accepts a pre-initialized `ReflagClient` instance. This is useful for advanced use cases where you need full control over client initialization or want to share a client instance across multiple parts of your application.
### ReflagClientProvider Usage
```vue
<script setup lang="ts">
import { ReflagClient } from "@reflag/browser-sdk";
import { ReflagClientProvider } from "@reflag/vue-sdk";
// Initialize the client yourself
const client = new ReflagClient({
publishableKey: "your-publishable-key",
user: { id: "user123", name: "John Doe" },
company: { id: "company456", name: "Acme Inc" },
// ... other configuration options
});
// Initialize the client
await client.initialize();
</script>
<template>
<ReflagClientProvider :client="client">
<template #loading>Loading...</template>
<Router />
</ReflagClientProvider>
</template>
```
### ReflagClientProvider Props
The `ReflagClientProvider` accepts the following props:
- `client`: A pre-initialized `ReflagClient` instance
### Slots
- `loading`: Optional slot to show while the client is initializing (same as `ReflagProvider`)
> [!Note]
> Most applications should use `ReflagProvider` or `ReflagBootstrappedProvider` instead of `ReflagClientProvider`. Only use this component when you need the advanced control it provides.
## Hooks
### `useFlag()`
Returns the state of a given flag for the current context. The composable provides access to flags and their configurations.
`useFlag()` returns an object with this shape:
```ts
{
isEnabled: boolean, // is the flag enabled
track: () => void, // send a track event when the flag is used
requestFeedback: (...) => void // open up a feedback dialog
config: {key: string, payload: any}, // remote configuration for this flag
isLoading: boolean // if you want to manage loading state at the flag level
}
```
Example:
```vue
<script setup lang="ts">
import { useFlag } from "@reflag/vue-sdk";
const { isEnabled, track, requestFeedback, config } = useFlag("huddles");
</script>
<template>
<div v-if="isLoading">Loading...</div>
<div v-else-if="!isEnabled">Flag not available</div>
<div v-else>
<button @click="track()">Start huddles!</button>
<button
@click="
(e) =>
requestFeedback({
title:
config.payload?.question ??
'How do you like the Huddles feature?',
position: {
type: 'POPOVER',
anchor: e.currentTarget as HTMLElement,
},
})
"
>
Give feedback!
</button>
</div>
</template>
```
See the reference docs for details.
### `useTrack()`
`useTrack()` returns a function which lets you send custom events to Reflag. It takes a string argument with the event name and optionally an object with properties to attach the event.
Using `track` returned from `useFlag()` calls this track function with the flag key as the event name.
```vue
<script setup lang="ts">
import { useTrack } from "@reflag/vue-sdk";
const track = useTrack();
</script>
<template>
<div>
<button @click="track('Huddles Started', { huddlesType: 'voice' })">
Start voice huddles!
</button>
</div>
</template>
```
### `useRequestFeedback()`
Returns a function that lets you open up a dialog to ask for feedback on a specific feature. This is useful for collecting targeted feedback about specific features.
See [Automated Feedback Surveys](https://docs.reflag.com/product-handbook/live-satisfaction) for how to do this automatically, without code.
When using the `useRequestFeedback` you must pass the flag key to `requestFeedback`.
The example below shows how to use `position` to ensure the popover appears next to the "Give feedback!" button.
```vue
<script setup lang="ts">
import { useRequestFeedback } from "@reflag/vue-sdk";
const requestFeedback = useRequestFeedback();
</script>
<template>
<button
@click="
(e) =>
requestFeedback({
flagKey: 'huddles',
title: 'How satisfied are you with file uploads?',
position: {
type: 'POPOVER',
anchor: e.currentTarget as HTMLElement,
},
// Optional custom styling
style: {
theme: 'light',
primaryColor: '#007AFF',
},
})
"
>
Give feedback!
</button>
</template>
```
See the [Feedback Documentation](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/FEEDBACK.md#manual-feedback-collection) for more information on `requestFeedback` options.
### `useSendFeedback()`
Returns a function that lets you send feedback to Reflag. This is useful if you've manually collected feedback through your own UI and want to send it to Reflag.
```vue
<script setup lang="ts">
import { useSendFeedback } from "@reflag/vue-sdk";
const sendFeedback = useSendFeedback();
const handleSubmit = async (data: FormData) => {
await sendFeedback({
flagKey: "reflag-flag-key",
score: parseInt(data.get("score") as string),
comment: data.get("comment") as string,
});
};
</script>
<template>
<form @submit="handleSubmit">
<!-- form content -->
</form>
</template>
```
### `useUpdateUser()`, `useUpdateCompany()` and `useUpdateOtherContext()`
These composables return functions that let you update the attributes for the currently set user, company, or other context. Updates to user/company are stored remotely and affect flag targeting, while "other" context updates only affect the current session.
```vue
<script setup lang="ts">
import {
useUpdateUser,
useUpdateCompany,
useUpdateOtherContext,
} from "@reflag/vue-sdk";
const updateUser = useUpdateUser();
const updateCompany = useUpdateCompany();
const updateOtherContext = useUpdateOtherContext();
const handleUserUpdate = async () => {
await updateUser({
role: "admin",
betaFeatures: "enabled",
});
};
const handleCompanyUpdate = async () => {
await updateCompany({
plan: "enterprise",
employees: 500,
});
};
const handleContextUpdate = async () => {
await updateOtherContext({
currentWorkspace: "workspace-123",
theme: "dark",
});
};
</script>
<template>
<div>
<button @click="handleUserUpdate">Update User</button>
<button @click="handleCompanyUpdate">Update Company</button>
<button @click="handleContextUpdate">Update Context</button>
</div>
</template>
```
Note: To change the `user.id` or `company.id`, you need to update the props passed to `ReflagProvider` instead of using these composables.
### `useClient()`
Returns the `ReflagClient` used by the `ReflagProvider`. The client offers more functionality that
is not directly accessible through the other composables.
```vue
<script setup>
import { useClient } from "@reflag/vue-sdk";
import { onMounted } from "vue";
const client = useClient();
console.log(client.getContext());
</script>
<template>
<!-- your component content -->
</template>
```
### `useIsLoading()`
Returns a `Ref<boolean>` to indicate if Reflag has finished loading.
Initially, the value will be `true` if no bootstrap flags have been provided and the client has not be initialized.
```vue
<script setup>
import { useIsLoading } from "@reflag/vue-sdk";
import { Spinner } from "./Spinner";
const isLoading = useIsLoading();
</script>
<template>
<!-- your component content -->
</template>
```
### `useOnEvent()`
Vue composable for listening to Reflag client events. This composable automatically handles mounting and unmounting of event listeners.
Available events include:
- `flagsUpdated`: Triggered when flags are updated
- `track`: Triggered when tracking events are sent
- `feedback`: Triggered when feedback is sent
```vue
<script setup lang="ts">
import { useOnEvent } from "@reflag/vue-sdk";
// Listen to flag updates
useOnEvent("flagsUpdated", () => {
console.log("Flags have been updated");
});
</script>
<template>
<!-- your component content -->
</template>
```
You can also provide a specific client instance if needed:
```vue
<script setup lang="ts">
import { ReflagClient } from "@reflag/browser-sdk";
const myReflagClient = new ReflagClient();
useOnEvent(
"flagsUpdated",
() => {
console.log("flags updated");
},
myReflagClient,
);
</script>
<template>
<!-- your component content -->
</template>
```
## Content Security Policy (CSP)
See [CSP](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Reflag React SDK with CSP
## License
MIT License
Copyright (c) 2025 Bucket ApS
```
--------------------------------------------------------------------------------
/sdk/@reflag/browser-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Reflag Browser SDK
Basic client for [Reflag.com](https://reflag.com). If you're using React, you'll be better off with the Reflag React SDK.
Reflag supports flag toggling, tracking flag usage, [collecting feedback](#qualitative-feedback-on-beta-flags) on flags, and [remotely configuring flags](#remote-config).
## Install
First find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag.
The package can be imported or used directly in a HTML script tag:
A. Import module:
```typescript
import { ReflagClient } from "@reflag/browser-sdk";
const user = {
id: 42,
role: "manager",
};
const company = {
id: 99,
plan: "enterprise",
};
const reflagClient = new ReflagClient({ publishableKey, user, company });
await reflagClient.initialize();
const {
isEnabled,
config: { payload: question },
track,
requestFeedback,
} = reflagClient.getFlag("huddle");
if (isEnabled) {
// Show flag. When retrieving `isEnabled` the client automatically
// sends a "check" event for the "huddle" flag which is shown in the
// Reflag UI.
// On usage, call `track` to let Reflag know that a user interacted with the flag
track();
// The `payload` is a user-supplied JSON in Reflag that is dynamically picked
// out depending on the user/company.
const question = payload?.question ?? "Tell us what you think of Huddles";
// Use `requestFeedback` to create "Send feedback" buttons easily for specific
// flags. This is not related to `track` and you can call them individually.
requestFeedback({ title: question });
}
// `track` just calls `reflagClient.track(<flagKey>)` to send an event using the same flag key
// You can also use `track` on the client directly to send any custom event.
reflagClient.track("huddle");
// similarly, `requestFeedback` just calls `reflagClient.requestFeedback({flagKey: <flagKey>})`
// which you can also call directly:
reflagClient.requestFeedback({ flagKey: "huddle" });
```
B. Script tag (client-side directly in html)
See [example/browser.html](https://github.com/reflagcom/javascript/tree/main/packages/browser-sdk/example/browser.html) for a working example:
```html
<script src="https://cdn.jsdelivr.net/npm/@reflag/browser-sdk@2"></script>
<script>
const reflag = new ReflagBrowserSDK.ReflagClient({
publishableKey: "publishableKey",
user: { id: "42" },
company: { id: "1" },
});
reflag.initialize().then(() => {
console.log("Reflag initialized");
document.getElementById("loading").style.display = "none";
document.getElementById("start-huddle").style.display = "block";
});
</script>
<span id="loading">Loading...</span>
<button
id="start-huddle"
style="display: none"
onClick="reflag.track('Started huddle')"
>
Click me
</button>
```
### Init options
Supply these to the constructor call:
```typescript
type Configuration = {
logger: console; // by default only logs warn/error, by passing `console` you'll log everything
apiBaseUrl?: "https://front.reflag.com";
sseBaseUrl?: "https://livemessaging.bucket.co";
feedback?: undefined; // See FEEDBACK.md
enableTracking?: true; // set to `false` to stop sending track events and user/company updates to Reflag servers. Useful when you're impersonating a user
fallbackFlags?:
| string[]
| Record<string, { key: string; payload: any } | true>; // Enable these flags if unable to contact reflag.com. Can be a list of flag keys or a record with configuration values
timeoutMs?: number; // Timeout for fetching flags (default: 5000ms)
staleWhileRevalidate?: boolean; // Revalidate in the background when cached flags turn stale to avoid latency in the UI (default: false)
staleTimeMs?: number; // at initialization time flags are loaded from the cache unless they have gone stale. Defaults to 0 which means the cache is disabled. Increase this in the case of a non-SPA
expireTimeMs?: number; // In case we're unable to fetch flags from Reflag, cached/stale flags will be used instead until they expire after `expireTimeMs`. Default is 30 days
offline?: boolean; // Use the SDK in offline mode. Offline mode is useful during testing and local development
};
```
## Migrating from Bucket SDK
If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
- `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
- `Feature*` classes, and types have been renamed to `Feature*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
- All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
- The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
- `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
- The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead og `bucket-*`
- The `featuresUpdated` hook has been renamed to `flagsUpdated`
- The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
- `getFeature` method is an alias for `getFlag`
- `getFeatures` method is an alias for `getFlags`
- `featuresUpdated` hook is an alias for `flagsUpdated`
If you are running with strict Content Security Policies active on your website, you will need change them as follows:
- `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
Finally, if you have customized the look & feel of the Feedback component, update `--bucket-feedback-*` CSS classes to `--reflag-feedback-*`
## Flag toggles
Reflag determines which flags are active for a given user/company. The user/company is given in the ReflagClient constructor.
If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
Attributes cannot be nested (multiple levels) and must be either strings, integers or booleans.
Some attributes are special and used in Reflag UI:
- `name` -- display name for `user`/`company`,
- `email` -- is accepted for `user`s and will be highlighted in the Reflag UI if available,
- `avatar` -- can be provided for both `user` and `company` and should be an URL to an image.
```ts
const reflagClient = new ReflagClient({
publishableKey,
user: {
id: "user_123",
name: "John Doe",
email: "[email protected]"
avatar: "https://example.com/images/udsy6363"
},
company: {
id: "company_123",
name: "Acme, Inc",
avatar: "https://example.com/images/31232ds"
},
});
```
To retrieve flags along with their targeting information, use `getFlag(key: string)`:
```ts
const huddle = reflagClient.getFlag("huddle");
// {
// isEnabled: true,
// config: { key: "zoom", payload: { ... } },
// track: () => Promise<Response>
// requestFeedback: (options: RequestFeedbackData) => void
// }
```
You can use `getFlags()` to retrieve all enabled flags currently.
```ts
const flags = reflagClient.getFlags();
// {
// huddle: {
// isEnabled: true,
// targetingVersion: 42,
// config: ...
// }
// }
```
`getFlags()` is meant to be more low-level than `getFlag()` and it typically used
by down-stream clients, like the React SDK.
Note that accessing `isEnabled` on the object returned by `getFlags` does not automatically
generate a `check` event, contrary to the `isEnabled` property on the object returned by `getFlag`.
## Remote config
Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
Similar to `isEnabled`, each flag has a `config` property. This configuration is managed from within Reflag.
It is managed similar to the way access to flags is managed, but instead of the binary `isEnabled` you can have
multiple configuration values which are given to different user/companies.
```ts
const flags = reflagClient.getFlags();
// {
// huddle: {
// isEnabled: true,
// targetingVersion: 42,
// config: {
// key: "gpt-3.5",
// payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
// }
// }
// }
```
`key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
Just as `isEnabled`, accessing `config` on the object returned by `getFlags` does not automatically
generate a `check` event, contrary to the `config` property on the object returned by `getFlag`.
## Server-side rendering and bootstrapping
For server-side rendered applications, you can eliminate the initial network request by bootstrapping the client with pre-fetched flag data.
### Init options bootstrapped
```typescript
type Configuration = {
logger: console; // by default only logs warn/error, by passing `console` you'll log everything
apiBaseUrl?: "https://front.reflag.com";
sseBaseUrl?: "https://livemessaging.bucket.co";
feedback?: undefined; // See FEEDBACK.md
enableTracking?: true; // set to `false` to stop sending track events and user/company updates to Reflag servers. Useful when you're impersonating a user
offline?: boolean; // Use the SDK in offline mode. Offline mode is useful during testing and local development
bootstrappedFlags?: FetchedFlags; // Pre-fetched flags from server-side (see Server-side rendering section)
};
```
### Using bootstrappedFlags
Use the Node SDK's `getFlagsForBootstrap()` method to pre-fetch flags server-side, then pass them to the browser client:
```typescript
// Server-side: Get flags using Node SDK
import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
const serverClient = new ReflagNodeClient({ secretKey: "your-secret-key" });
await serverClient.initialize();
const { flags } = serverClient.getFlagsForBootstrap({
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
});
// Pass flags data to client using your framework's preferred method
// or for example in a script tag
app.get("/", (req, res) => {
res.set("Content-Type", "text/html");
res.send(
Buffer.from(
`<script>var flags = ${JSON.stringify(flags)};</script>
<main id="app"></main>`,
),
);
});
// Client-side: Initialize with pre-fetched flags
import { ReflagClient } from "@reflag/browser-sdk";
const reflagClient = new ReflagClient({
publishableKey: "your-publishable-key",
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
bootstrappedFlags: flags, // No network request needed
});
await reflagClient.initialize(); // Initializes all but flags
const { isEnabled } = reflagClient.getFlag("huddle");
```
This eliminates loading states and improves performance by avoiding the initial flags API call.
## Context management
### Updating user/company/other context
Attributes given for the user/company/other context in the ReflagClient constructor can be updated for use in flag targeting evaluation with the `updateUser()`, `updateCompany()` and `updateOtherContext()` methods.
They return a promise which resolves once the flags have been re-evaluated follow the update of the attributes.
The following shows how to let users self-opt-in for a new flag. The flag must have the rule `voiceHuddleOptIn IS true` set in the Reflag UI.
```ts
// toggle opt-in for the voiceHuddle flag:
const { isEnabled } = reflagClient.getFlag("voiceHuddle");
// this toggles the flag on/off. The promise returns once flag targeting has been
// re-evaluated.
await reflagClient.updateUser({ voiceHuddleOptIn: (!isEnabled).toString() });
```
{% hint style="info" %}
{% endhint %}
### setContext()
The `setContext()` method allows you to replace the entire context (user, company, and other attributes) at once. This method is useful when you need to completely change the context, such as when a user logs in or switches between different accounts.
```ts
await reflagClient.setContext({
user: {
id: "new-user-123",
name: "Jane Doe",
email: "[email protected]",
role: "admin",
},
company: {
id: "company-456",
name: "New Company Inc",
plan: "enterprise",
},
other: {
feature: "beta",
locale: "en-US",
},
});
```
The method will:
- Replace the entire context with the new values
- Re-evaluate all flags based on the new context
- Update the user and company information on Reflag servers
- Return a promise that resolves once the flags have been re-evaluated
### getContext()
The `getContext()` method returns the current context being used for flag evaluation. This is useful for debugging or when you need to inspect the current user, company, and other attributes.
```ts
const currentContext = reflagClient.getContext();
console.log(currentContext);
// {
// user: { id: "user-123", name: "John Doe", email: "[email protected]" },
// company: { id: "company-456", name: "Acme Inc", plan: "enterprise" },
// other: { locale: "en-US", feature: "beta" }
// }
```
The returned context object contains:
- `user`: Current user attributes (if any)
- `company`: Current company attributes (if any)
- `other`: Additional context attributes not related to user or company
## Toolbar
The Reflag Toolbar is great for toggling flags on/off for yourself to ensure that everything works both when a flag is on and when it's off.
<img width="352" alt="Toolbar screenshot" src="https://github.com/user-attachments/assets/c223df5a-4bd8-49a1-8b4a-ad7001357693" />
The toolbar will automatically appear on `localhost`. However, it can also be incredibly useful in production.
You have full control over when it appears through the `toolbar` configuration option passed to the `ReflagClient`.
You can pass a simple boolean to force the toolbar to appear/disappear:
```typescript
const client = new ReflagClient({
// show the toolbar even in production if the user is an internal/admin user
toolbar: user?.isInternal,
...
});
```
You can also configure the position of the toolbar on the screen:
```typescript
const client = new ReflagClient({
toolbar: {
show: true;
position: {
placement: "bottom-left",
offset: {x: "1rem", y: "1rem"}
}
}
...
})
```
See [the reference](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for details.
## Qualitative feedback on beta flags
Reflag can collect qualitative feedback from your users in the form of a [Customer Satisfaction Score](https://en.wikipedia.org/wiki/Customer_satisfaction) and a comment.
### Automated feedback collection
The Reflag Browser SDK comes with automated feedback collection mode enabled by default, which lets the Reflag service ask your users for feedback for relevant flags just after they've used them.
{% hint style="info" %}
To get started with automatic feedback collection, make sure you've set `user` in the `ReflagClient` constructor.
{% endhint %}
Automated feedback surveys work even if you're not using the SDK to send events to Reflag.
It works because the Reflag Browser SDK maintains a live connection to Reflag's servers and can automatically show a feedback prompt whenever the Reflag servers determines that an event should trigger a prompt - regardless of how this event is sent to Reflag.
You can find all the options to make changes to the default behavior in the [Reflag feedback documentation](../../documents/browser-sdk/FEEDBACK.md).
### Reflag feedback UI
Reflag can assist you with collecting your user's feedback by offering a pre-built UI, allowing you to get started with minimal code and effort.
[Read the Reflag feedback UI documentation](../../documents/browser-sdk/FEEDBACK.md)
### Reflag feedback SDK
Feedback can be submitted to Reflag using the SDK:
```ts
reflagClient.feedback({
flagKey: "my-flag-key", // String (required), copy from Flag feedback tab
score: 5, // Number: 1-5 (optional)
comment: "Absolutely stellar work!", // String (optional)
});
```
### Reflag feedback API
If you are not using the Reflag Browser SDK, you can still submit feedback using the HTTP API.
See details in [Feedback HTTP API](https://docs.reflag.com/api/http-api#post-feedback)
## Tracking flag usage
The `track` function lets you send events to Reflag to denote flag usage.
By default Reflag expects event names to align with the flag keys, but
you can customize it as you wish.
```ts
reflagClient.track("huddle", { voiceHuddle: true });
```
## Event listeners
Event listeners allow for capturing various events occurring in the `ReflagClient`. This is useful to build integrations with other system or for various debugging purposes. There are 5 kinds of events:
- `check`: Your code used `isEnabled` or `config` for a flag
- `flagsUpdated`: Flags were updated. Either because they were loaded as part of initialization or because the user/company updated
- `user`: User information updated (similar to the `identify` call used in tracking terminology)
- `company`: Company information updated (sometimes to the `group` call used in tracking terminology)
- `track`: Track event occurred.
Use the `on()` method to add an event listener to respond to certain events. See the API reference for details on each hook.
```ts
import { ReflagClient, CheckEvent, RawFlags } from "@reflag/browser-sdk";
const client = new ReflagClient({
// options
});
// or add the hooks after construction:
const unsub = client.on("check", (check: CheckEvent) =>
console.log(`Check event ${check}`),
);
// use the returned function to unsubscribe, or call `off()` with the same arguments again
unsub();
```
## Zero PII
The Reflag Browser SDK doesn't collect any metadata and HTTP IP addresses are _not_ being stored.
For tracking individual users, we recommend using something like database ID as userId, as it's unique and doesn't include any PII (personal identifiable information). If, however, you're using e.g. email address as userId, but prefer not to send any PII to Reflag, you can hash the sensitive data before sending it to Reflag:
```ts
import reflag from "@reflag/browser-sdk";
import { sha256 } from "crypto-hash";
reflag.user(await sha256("john_doe"));
```
## Use of cookies
The Reflag Browser SDK uses a couple of cookies to support automated feedback surveys. These cookies are not used for tracking purposes and thus should not need to appear in cookie consent forms.
The two cookies are:
- `reflag-prompt-${userId}`: store the last automated feedback prompt message ID received to avoid repeating surveys
- `reflag-token-${userId}`: caching a token used to connect to Reflag's live messaging infrastructure that is used to deliver automated feedback surveys in real time.
## TypeScript
Types are bundled together with the library and exposed automatically when importing through a package manager.
## Content Security Policy (CSP)
If you are running with strict Content Security Policies active on your website, you will need to enable these directives in order to use the SDK:
| Directive | Values | Reason |
| ----------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| connect-src | [https://front.reflag.com](https://front.reflag.com) | Basic functionality` |
| connect-src | [https://livemessaging.bucket.co](https://livemessaging.bucket.co) | Server sent events for use in automated feedback surveys, which allows for automatically collecting feedback when a user used a flag. |
| style-src | 'unsafe-inline' | The feedback UI is styled with inline styles. Not having this directive results unstyled HTML elements. |
If you are including the Reflag tracking SDK with a `<script>`-tag from `jsdelivr.net` you will also need:
| Directive | Values | Reason |
| --------------- | ---------------------------------------------------- | ------------------------------- |
| script-src-elem | [https://cdn.jsdelivr.net](https://cdn.jsdelivr.net) | Loads the Reflag SDK from a CDN |
## License
> MIT License
> Copyright (c) 2025 Bucket ApS
```
--------------------------------------------------------------------------------
/sdk/@reflag/react-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Reflag React SDK
React client side library for [Reflag.com](https://reflag.com)
Reflag supports flag toggling, tracking flag usage, [requesting feedback](#userequestfeedback) on features, and [remotely configuring flags](#remote-config).
The Reflag React SDK comes with a [built-in toolbar](https://docs.reflag.com/supported-languages/browser-sdk#toolbar) which appears on `localhost` by default.
## Install
Install via npm:
```shell
npm i @reflag/react-sdk
```
## Get started
### 1. Add the `ReflagProvider` context provider
Add the `ReflagProvider` context provider to your application:
**Example:**
```tsx
import { ReflagProvider } from "@reflag/react-sdk";
<ReflagProvider
publishableKey="{YOUR_PUBLISHABLE_KEY}"
context={{
company: { id: "acme_inc", plan: "pro" },
user: { id: "john doe" },
}}
loadingComponent={<Loading />}
>
{/* children here are shown when loading finishes or immediately if no `loadingComponent` is given */}
</ReflagProvider>;
```
### 2. Create a new flag and set up type safety
Install the Reflag CLI:
```shell
npm i --save-dev @reflag/cli
```
Run `npx reflag new` to create your first flag!
On the first run, it will sign into Reflag and set up type generation for your project:
```shell
❯ npx reflag new
Opened web browser to facilitate login: https://app.reflag.com/api/oauth/cli/authorize
Welcome to ◪ Reflag!
? Where should we generate the types? gen/flags.d.ts
? What is the output format? react
✔ Configuration created at reflag.config.json.
Creating flag for app Slick app.
? New flag name: Huddle
? New flag key: huddle
✔ Created flag Huddle with key huddle (https://app.reflag.com/features/huddles)
✔ Generated react types in gen/flags.d.ts.
```
> [!Note]
> By default, types will be generated in `gen/flags.d.ts`.
> The default `tsconfig.json` file `include`s this file by default, but if your `tsconfig.json` is different, make sure the file is covered in the `include` property.
### 3. Use `useFlag(<flagKey>)` to get flag status
Using the `useFlag` hook from your components lets you toggle flags on/off and track flag usage:
**Example:**
```tsx
function StartHuddleButton() {
const {
isEnabled, // boolean indicating if the flag is enabled
track, // track usage of the flag
} = useFlag("huddle");
if (!isEnabled) {
return null;
}
return <button onClick={track}>Start huddle!</button>;
}
```
`useFlag` can help you do much more. See a full example for `useFlag` [see below](#useflag).
## Setting context
Reflag determines which flags are active for a given `user`, `company`, or `other` context.
You can pass these to the `ReflagProvider` using the `context` prop.
### Using the `context` prop
```tsx
<ReflagProvider
publishableKey={YOUR_PUBLISHABLE_KEY}
context={{
user: { id: "user_123", name: "John Doe", email: "[email protected]" },
company: { id: "company_123", name: "Acme, Inc" },
other: { source: "web" },
}}
>
<LoadingReflag>
{/* children here are shown when loading finishes */}
</LoadingReflag>
</ReflagProvider>
```
### Legacy individual props (deprecated)
For backward compatibility, you can still use individual props, but these are deprecated and will be removed in the next major version:
```tsx
<ReflagProvider
publishableKey={YOUR_PUBLISHABLE_KEY}
user={{ id: "user_123", name: "John Doe", email: "[email protected]" }}
company={{ id: "company_123", name: "Acme, Inc" }}
otherContext={{ source: "web" }}
>
<LoadingReflag>
{/* children here are shown when loading finishes */}
</LoadingReflag>
</ReflagProvider>
```
> [!Important]
> The `user`, `company`, and `otherContext` props are deprecated. Use the `context` prop instead, which provides the same functionality in a more structured way.
### Context requirements
If you supply `user` or `company` objects, they must include at least the `id` property otherwise they will be ignored in their entirety.
In addition to the `id`, you must also supply anything additional that you want to be able to evaluate flag targeting rules against.
Attributes which are not properties of the `user` or `company` can be supplied using the `other` property.
Attributes cannot be nested (multiple levels) and must be either strings, numbers or booleans.
A number of special attributes exist:
- `name` -- display name for `user`/`company`,
- `email` -- the email of the user,
- `avatar` -- the URL for `user`/`company` avatar image.
To retrieve flags along with their targeting information, use `useFlag(key: string)` hook (described in a section below).
Note that accessing `isEnabled` on the object returned by `useFlag()` automatically
generates a `check` event.
## Remote config
Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
Similar to `isEnabled`, each flag accessed using the `useFlag()` hook, has a `config` property. This configuration is managed from within Reflag. It is managed similar to the way access to flags is managed, but instead of the
binary `isEnabled` you can have multiple configuration values which are given to different user/companies.
### Get started with Remote config
1. Update your flag definitions:
```typescript
import "@reflag/react-sdk";
// Define your flags by extending the `Flags` interface in @reflag/react-sdk
declare module "@reflag/react-sdk" {
interface Flags {
huddle: {
// change from `boolean` to an object which sets
// a type for the remote config for `questionnaire`
maxTokens: number;
model: string;
};
}
}
```
```ts
const {
isEnabled,
config: { key, payload },
} = useFlag("huddles");
// isEnabled: true,
// key: "gpt-3.5",
// payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
```
`key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
Note that, similar to `isEnabled`, accessing `config` on the object returned by `useFlag()` automatically
generates a `check` event.
## Toolbar
The Reflag Toolbar is great for toggling flags on/off for yourself to ensure that everything works both when a flag is on and when it's off.
<img width="310" height="265" alt="Toolbar" src="https://github.com/user-attachments/assets/61492915-0d30-446d-a163-3eb16d9024b2" />
The toolbar will automatically appear on `localhost`. However, it can also be incredibly useful in production. You have full control over when it appears through the `toolbar` configuration option passed to the ReflagProvider.
You can pass a simple boolean to force the toolbar to appear/disappear:
```ts
<ReflagProvider
...
// show the toolbar even in production if the user is an internal/admin user
toolbar={user?.isInternal}
...
});
```
## Server-side rendering and bootstrapping
For server-side rendered applications, you can eliminate the initial network request by bootstrapping the client with pre-fetched flag data using the `ReflagBootstrappedProvider`.
### Using `ReflagBootstrappedProvider`
The `<ReflagBootstrappedProvider>` component is a specialized version of `ReflagProvider` designed for server-side rendering and preloaded flag scenarios. Instead of fetching flags on initialization, it uses pre-fetched flags, resulting in faster initial page loads and better SSR compatibility.
```tsx
import { useState, useEffect } from "react";
import { BootstrappedFlags } from "@reflag/react-sdk";
interface BootstrapData {
user: User;
flags: BootstrappedFlags;
}
function useBootstrap() {
const [data, setData] = useState<BootstrapData | null>(null);
useEffect(() => {
fetch("/bootstrap")
.then((res) => res.json())
.then(setData);
}, []);
return data;
}
// Usage in your app
function App() {
const { user, flags } = useBootstrap();
return (
<AuthProvider user={user}>
<ReflagBootstrappedProvider
publishableKey="your-publishable-key"
flags={flags}
>
<Router />
</ReflagBootstrappedProvider>
</AuthProvider>
);
}
```
### Server-side endpoint setup
Create an endpoint that provides bootstrap data to your client application:
```typescript
// server.js or your Express app
import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
const reflagClient = new ReflagNodeClient({
secretKey: process.env.REFLAG_SECRET_KEY,
});
await reflagClient.initialize();
app.get("/bootstrap", (req, res) => {
const user = getUser(req); // Get user from your auth system
const company = getCompany(req); // Get company from your auth system
const flags = reflagClient.getFlagsForBootstrap({
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
other: { source: "web" },
});
res.status(200).json({
user,
flags,
});
});
```
### Next.js Page Router SSR example
For Next.js applications using server-side rendering, you can pre-fetch flags in `getServerSideProps`:
```typescript
// pages/index.tsx
import { GetServerSideProps } from "next";
import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
import { ReflagBootstrappedProvider, BootstrappedFlags, useFlag } from "@reflag/react-sdk";
interface PageProps {
bootstrapData: BootstrappedFlags;
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const serverClient = new ReflagNodeClient({
secretKey: process.env.REFLAG_SECRET_KEY
});
await serverClient.initialize();
const user = await getUserFromSession(context.req);
const company = await getCompanyFromUser(user);
const bootstrapData = serverClient.getFlagsForBootstrap({
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
other: { page: "homepage" }
});
return { props: { bootstrapData } };
};
export default function HomePage({ bootstrapData }: PageProps) {
return (
<ReflagBootstrappedProvider
publishableKey={process.env.NEXT_PUBLIC_REFLAG_PUBLISHABLE_KEY}
flags={bootstrapData}
>
<HuddleFeature />
</ReflagBootstrappedProvider>
);
}
function HuddleFeature() {
const { isEnabled, track, config } = useFlag("huddle");
if (!isEnabled) return null;
return (
<div>
<h2>Start a Huddle</h2>
<p>Max participants: {config.payload?.maxParticipants ?? 10}</p>
<p>Video quality: {config.payload?.videoQuality ?? "standard"}</p>
<button onClick={track}>Start Huddle</button>
</div>
);
}
```
This approach eliminates loading states and improves performance by avoiding the initial flags API call.
### Next.js App Router example
For Next.js applications using the App Router (Next.js 13+), you can pre-fetch flags in Server Components and pass them to client components:
```typescript
// app/layout.tsx (Server Component)
import { ReflagClient as ReflagNodeClient } from "@reflag/node-sdk";
import { ClientProviders } from "./providers";
async function getBootstrapData() {
const serverClient = new ReflagNodeClient({
secretKey: process.env.REFLAG_SECRET_KEY!
});
await serverClient.initialize();
// In a real app, you'd get user/company from your auth system
const bootstrapData = serverClient.getFlagsForBootstrap({
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
other: { source: "web" }
});
return bootstrapData;
}
export default async function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const bootstrapData = await getBootstrapData();
return (
<html lang="en">
<body>
<ClientProviders bootstrapData={bootstrapData}>
{children}
</ClientProviders>
</body>
</html>
);
}
```
```typescript
// app/providers.tsx (Client Component)
"use client";
import { ReflagBootstrappedProvider, BootstrappedFlags } from "@reflag/react-sdk";
interface ClientProvidersProps {
children: React.ReactNode;
bootstrapData: BootstrappedFlags;
}
export function ClientProviders({ children, bootstrapData }: ClientProvidersProps) {
return (
<ReflagBootstrappedProvider
publishableKey={process.env.NEXT_PUBLIC_REFLAG_PUBLISHABLE_KEY!}
flags={bootstrapData}
>
{children}
</ReflagBootstrappedProvider>
);
}
```
```typescript
// app/page.tsx (Server Component)
import { HuddleFeature } from "./huddle-feature";
export default function HomePage() {
return (
<main>
<h1>My App</h1>
<HuddleFeature />
</main>
);
}
```
```typescript
// app/huddle-feature.tsx (Client Component)
"use client";
import { useFlag } from "@reflag/react-sdk";
export function HuddleFeature() {
const { isEnabled, track, config } = useFlag("huddle");
if (!isEnabled) return null;
return (
<div>
<h2>Start a Huddle</h2>
<p>Max participants: {config.payload?.maxParticipants ?? 10}</p>
<p>Video quality: {config.payload?.videoQuality ?? "standard"}</p>
<button onClick={track}>Start Huddle</button>
</div>
);
}
```
This App Router approach leverages Server Components for server-side flag fetching while using Client Components only where React state and hooks are needed.
## `<ReflagClientProvider>` component
The `<ReflagClientProvider>` is a lower-level component that accepts a pre-initialized `ReflagClient` instance. This is useful for advanced use cases where you need full control over client initialization or want to share a client instance across multiple parts of your application.
### Usage
```tsx
import { ReflagClient } from "@reflag/browser-sdk";
import { ReflagClientProvider } from "@reflag/react-sdk";
// Initialize the client yourself
const client = new ReflagClient({
publishableKey: "your-publishable-key",
user: { id: "user123", name: "John Doe" },
company: { id: "company456", name: "Acme Inc" },
// ... other configuration options
});
// Initialize the client
await client.initialize();
function App() {
return (
<ReflagClientProvider client={client} loadingComponent={<Loading />}>
<Router />
</ReflagClientProvider>
);
}
```
### Props
The `ReflagClientProvider` accepts the following props:
- `client`: A pre-initialized `ReflagClient` instance
- `loadingComponent`: Optional React component to show while the client is initializing (same as `ReflagProvider`)
> [!Note]
> Most applications should use `ReflagProvider` or `ReflagBootstrappedProvider` instead of `ReflagClientProvider`. Only use this component when you need the advanced control it provides.
## `<ReflagProvider>` component
The `<ReflagProvider>` initializes the Reflag SDK, fetches flags and starts listening for automated feedback survey events. The component can be configured using a number of props:
- `publishableKey` is used to connect the provider to an _environment_ on Reflag. Find your `publishableKey` under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag,
- `context` (recommended): An object containing `user`, `company`, and `other` properties that make up the evaluation context used to determine if a flag is enabled or not. `company` and `user` contexts are automatically transmitted to Reflag servers so the Reflag app can show you which companies have access to which flags etc.
- `company`, `user` and `other` (deprecated): Individual props for context. These are deprecated in favor of the `context` prop and will be removed in the next major version.
> [!Note]
> If you specify `company` and/or `user` they must have at least the `id` property, otherwise they will be ignored in their entirety. You should also supply anything additional you want to be able to evaluate flag targeting against,
- `fallbackFlags`: A list of strings which specify which flags to consider enabled if the SDK is unable to fetch flags. Can be provided in two formats:
```ts
// Simple array of flag keys
fallbackFlags={["flag1", "flag2"]}
// Or with configuration overrides
fallbackFlags: {
"flag1": true, // just enable the flag
"flag2": { // enable with configuration
key: "variant-a",
payload: {
limit: 100,
mode: "test"
}
}
}
```
- `timeoutMs`: Timeout in milliseconds when fetching flags from the server.
- `staleWhileRevalidate`: If set to `true`, stale flags will be returned while refetching flags in the background.
- `expireTimeMs`: If set, flags will be cached between page loads for this duration (in milliseconds).
- `staleTimeMs`: Maximum time (in milliseconds) that stale flags will be returned if `staleWhileRevalidate` is true and new flags cannot be fetched.
- `offline`: Provide this option when testing or in local development environments to avoid contacting Reflag servers.
- `loadingComponent` lets you specify an React component to be rendered instead of the children while the Reflag provider is initializing. If you want more control over loading screens, `useFlag()` and `useIsLoading` returns `isLoading` which you can use to customize the loading experience.
- `enableTracking`: Set to `false` to stop sending tracking events and user/company updates to Reflag. Useful when you're impersonating a user (defaults to `true`),
- `apiBaseUrl`: Optional base URL for the Reflag API. Use this to override the default API endpoint,
- `appBaseUrl`: Optional base URL for the Reflag application. Use this to override the default app URL,
- `sseBaseUrl`: Optional base URL for Server-Sent Events. Use this to override the default SSE endpoint,
- `debug`: Set to `true` to enable debug logging to the console,
- `toolbar`: Optional [configuration](https://docs.reflag.com/supported-languages/browser-sdk/globals#toolbaroptions) for the Reflag toolbar,
- `feedback`: Optional configuration for feedback collection
## `<ReflagBootstrappedProvider>` component
The `<ReflagBootstrappedProvider>` is a specialized version of the `ReflagProvider` that uses pre-fetched flag data instead of making network requests during initialization. This is ideal for server-side rendering scenarios.
The component accepts the following props:
- `flags`: Pre-fetched flags data of type `BootstrappedFlags` obtained from the Node SDK's `getFlagsForBootstrap()` method. This contains both the context (user, company, other) and the flags data.
- All other props available in [`ReflagProvider`](#reflagprovider-component) are supported except `context`, `user`, `company`, and `other` (which are extracted from `flags.context`).
**Example:**
```tsx
import {
ReflagBootstrappedProvider,
BootstrappedFlags,
} from "@reflag/react-sdk";
interface AppProps {
bootstrapData: BootstrappedFlags;
}
function App({ bootstrapData }: AppProps) {
return (
<ReflagBootstrappedProvider
publishableKey="your-publishable-key"
flags={bootstrapData}
loadingComponent={<Loading />}
debug={process.env.NODE_ENV === "development"}
>
<Router />
</ReflagBootstrappedProvider>
);
}
```
> [!Note]
> When using `ReflagBootstrappedProvider`, the context (user, company, and other) is extracted from the `flags.context` property and doesn't need to be passed separately.
## Hooks
### `useFlag()`
Returns the state of a given flag for the current context. The hook provides type-safe access to flags and their configurations.
```tsx
import { useFlag } from "@reflag/react-sdk";
import { Loading } from "./Loading";
function StartHuddleButton() {
const {
isLoading, // true while flags are being loaded
isEnabled, // boolean indicating if the flag is enabled
config: {
// flag configuration
key, // string identifier for the config variant
payload, // type-safe configuration object
},
track, // function to track flag usage
requestFeedback, // function to request feedback for this flag
} = useFlag("huddle");
if (isLoading) {
return <Loading />;
}
if (!isEnabled) {
return null;
}
return (
<>
<button onClick={track}>Start huddle!</button>
<button
onClick={(e) =>
requestFeedback({
title: payload?.question ?? "How do you like the Huddles feature?",
position: {
type: "POPOVER",
anchor: e.currentTarget as HTMLElement,
},
})
}
>
Give feedback!
</button>
</>
);
}
```
### `useTrack()`
`useTrack()` lets you send custom events to Reflag. Use this whenever a user _uses_ a feature. These events can be used to analyze feature usage in Reflag.
```tsx
import { useTrack } from "@reflag/react-sdk";
function StartHuddle() {
const { track } = useTrack();
<div>
<button onClick={() => track("Huddle Started", { huddleType: "voice" })}>
Start voice huddle!
</button>
</div>;
}
```
### `useRequestFeedback()`
`useRequestFeedback()` returns a function that lets you open up a dialog to ask for feedback on a specific feature. This is useful for collecting targeted feedback about specific features as part of roll out. See [Automated Feedback Surveys](https://docs.reflag.com/product-handbook/live-satisfaction) for how to do this automatically, without code.
When using the `useRequestFeedback` you must pass the flag key to `requestFeedback`.
The example below shows how to use `position` to ensure the popover appears next to the "Give feedback!" button.
```tsx
import { useRequestFeedback } from "@reflag/react-sdk";
function FeedbackButton() {
const requestFeedback = useRequestFeedback();
return (
<button
onClick={(e) =>
requestFeedback({
flagKey: "huddle-flag",
title: "How satisfied are you with file uploads?",
position: {
type: "POPOVER",
anchor: e.currentTarget as HTMLElement,
},
// Optional custom styling
style: {
theme: "light",
primaryColor: "#007AFF",
},
})
}
>
Give feedback!
</button>
);
}
```
See the [Feedback Documentation](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/FEEDBACK.md#manual-feedback-collection) for more information on `requestFeedback` options.
### `useSendFeedback()`
Returns a function that lets you send feedback to Reflag. This is useful if you've manually collected feedback through your own UI and want to send it to Reflag.
```tsx
import { useSendFeedback } from "@reflag/react-sdk";
function CustomFeedbackForm() {
const sendFeedback = useSendFeedback();
const handleSubmit = async (data: FormData) => {
await sendFeedback({
flagKey: "reflag-flag-key",
score: parseInt(data.get("score") as string),
comment: data.get("comment") as string,
});
};
return <form onSubmit={handleSubmit}>...</form>;
}
```
### `useUpdateUser()`, `useUpdateCompany()` and `useUpdateOtherContext()`
These hooks return functions that let you update the attributes for the currently set user, company, or other context. Updates to user/company are stored remotely and affect flag targeting, while "other" context updates only affect the current session.
```tsx
import {
useUpdateUser,
useUpdateCompany,
useUpdateOtherContext,
} from "@reflag/react-sdk";
function FlagOptIn() {
const updateUser = useUpdateUser();
const updateCompany = useUpdateCompany();
const updateOtherContext = useUpdateOtherContext();
const handleUserUpdate = async () => {
await updateUser({
role: "admin",
betaFlags: "enabled",
});
};
const handleCompanyUpdate = async () => {
await updateCompany({
plan: "enterprise",
employees: 500,
});
};
const handleContextUpdate = async () => {
await updateOtherContext({
currentWorkspace: "workspace-123",
theme: "dark",
});
};
return (
<div>
<button onClick={handleUserUpdate}>Update User</button>
<button onClick={handleCompanyUpdate}>Update Company</button>
<button onClick={handleContextUpdate}>Update Context</button>
</div>
);
}
```
### `useClient()`
Returns the `ReflagClient` used by the `ReflagProvider`. The client offers more functionality that
is not directly accessible thorough the other hooks.
```tsx
import { useClient } from "@reflag/react-sdk";
function LoggingWrapper({ children }: { children: ReactNode }) {
const client = useClient();
console.log(client.getContext());
return children;
}
```
### `useIsLoading()`
Returns the loading state of the flags in the `ReflagClient`.
Initially, the value will be `true` if no bootstrap flags have been provided and the client has not be initialized.
```tsx
import { useIsLoading } from "@reflag/react-sdk";
import { Spinner } from "./Spinner";
function LoadingWrapper({ children }: { children: ReactNode }) {
const isLoading = useIsLoading();
if (isLoading) {
return <Spinner />;
}
return children;
}
```
### `useOnEvent()`
Attach a callback handler to client events to act on changes. It automatically disposes itself on unmount.
```tsx
import { useOnEvent } from "@reflag/react-sdk";
function LoggingWrapper({ children }: { children: ReactNode }) {
useOnEvent("flagsUpdated", (newFlags) => {
console.log(newFlags);
});
return children;
}
```
## Migrating from Bucket SDK
If you have been using the Bucket SDKs, the following list will help you migrate to Reflag SDK:
- `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
- `Feature*` classes, and types have been renamed to `Flag*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
- When using strongly-typed flags, the new `Flags` interface replaced `Features` interface
- All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
- The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
- `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
- The SDKs will not emit `evaluate` and `evaluate-config` events anymore
- The new cookies that are stored in the client's browser are now `reflag-*` prefixed instead of `bucket-*`
- The `featuresUpdated` hook has been renamed to `flagsUpdated`
- The `checkIsEnabled` and `checkConfig` hooks have been removed, use `check` from now on
To ease in transition to Reflag SDK, some of the old methods have been preserved as aliases to the new methods:
- `getFeature` method is an alias for `getFlag`
- `getFeatures` method is an alias for `getFlags`
- `useFeature` method is an alias for `useFlag`
- `featuresUpdated` hook is an alias for `flagsUpdated`
If you are running with strict Content Security Policies active on your website, you will need change them as follows:
- `connect-src https://front.bucket.co` to `connect-src https://front.reflag.com`
## Content Security Policy (CSP)
See [CSP](https://github.com/reflagcom/javascript/blob/main/packages/browser-sdk/README.md#content-security-policy-csp) for info on using Reflag React SDK with CSP
## License
MIT License
Copyright (c) 2025 Bucket ApS
```
--------------------------------------------------------------------------------
/sdk/@reflag/node-sdk/README.md:
--------------------------------------------------------------------------------
```markdown
---
layout:
visible: true
title:
visible: true
description:
visible: false
tableOfContents:
visible: true
outline:
visible: true
pagination:
visible: true
---
# Reflag Node.js SDK
Node.js, JavaScript/TypeScript client for [Reflag.com](https://reflag.com).
Reflag supports flag toggling, tracking flag usage, collecting feedback on features, and [remotely configuring flags](#remote-config).
## Installation
Install using your favorite package manager:
{% tabs %}
{% tab title="npm" %}
```sh
npm i @reflag/node-sdk
```
{% endtab %}
{% tab title="yarn" %}
```sh
yarn add @reflag/node-sdk
```
{% endtab %}
{% tab title="bun" %}
```sh
bun add @reflag/node-sdk
```
{% endtab %}
{% tab title="pnpm" %}
```sh
pnpm add @reflag/node-sdk
```
{% endtab %}
{% tab title="deno" %}
```sh
deno add npm:@reflag/node-sdk
```
{% endtab %}
{% endtabs %}
Other supported languages/frameworks are in the [Supported languages](https://docs.reflag.com/quickstart/supported-languages) documentation pages.
You can also [use the HTTP API directly](https://docs.reflag.com/api/http-api)
## Basic usage
To get started you need to obtain your secret key from the [environment settings](https://app.reflag.com/env-current/settings/app-environments)
in Reflag.
{% hint style="danger" %}
Secret keys are meant for use in server side SDKs only. Secret keys offer the users the ability to obtain
information that is often sensitive and thus should not be used in client-side applications.
{% endhint %}
Reflag will load settings through the various environment variables automatically (see [Configuring](#configuring) below).
1. Find the Reflag secret key for your development environment under [environment settings](https://app.reflag.com/env-current/settings/app-environments) in Reflag.
2. Set `REFLAG_SECRET_KEY` in your `.env` file
3. Create a `reflag.ts` file containing the following:
```typescript
import { ReflagClient } from "@reflag/node-sdk";
// Create a new instance of the client with the secret key. Additional options
// are available, such as supplying a logger and other custom properties.
//
// We recommend that only one global instance of `client` should be created
// to avoid multiple round-trips to our servers.
export const reflagClient = new ReflagClient();
// Initialize the client and begin fetching flag targeting definitions.
// You must call this method prior to any calls to `getFlags()`,
// otherwise an empty object will be returned.
reflagClient.initialize().then(() => {
console.log("Reflag initialized!");
});
```
Once the client is initialized, you can obtain flags along with the `isEnabled`
status to indicate whether the flag is targeted for this user/company:
{% hint style="warning" %}
If `user.id` or `company.id` is not given, the whole `user` or `company` object is ignored.
{% endhint %}
```typescript
// configure the client
const boundClient = reflagClient.bindClient({
user: {
id: "john_doe",
name: "John Doe",
email: "[email protected]",
avatar: "https://example.com/users/jdoe",
},
company: {
id: "acme_inc",
name: "Acme, Inc.",
avatar: "https://example.com/companies/acme",
},
});
// get the huddle flag using company, user and custom context to
// evaluate the targeting.
const { isEnabled, track, config } = boundClient.getFlag("huddle");
if (isEnabled) {
// this is your flag gated code ...
// send an event when the flag is used:
track();
if (config?.key === "zoom") {
// this code will run if a given remote configuration
// is set up.
}
// CAUTION: if you plan to use the event for automated feedback surveys
// call `flush` immediately after `track`. It can optionally be awaited
// to guarantee the sent happened.
boundClient.flush();
}
```
You can also use the `getFlags()` method which returns a map of all flags:
```typescript
// get the current flags (uses company, user and custom context to
// evaluate the flags).
const flags = boundClient.getFlags();
const bothEnabled = flags.huddle?.isEnabled && flags.voiceHuddle?.isEnabled;
```
## High performance flag targeting
The SDK contacts the Reflag servers when you call `initialize()`
and downloads the flags with their targeting rules.
These rules are then matched against the user/company information you provide
to `getFlags()` (or through `bindClient(..).getFlags()`). That means the
`getFlags()` call does not need to contact the Reflag servers once
`initialize()` has completed. `ReflagClient` will continue to periodically
download the targeting rules from the Reflag servers in the background.
### Batch Operations
The SDK automatically batches operations like user/company updates and flag tracking events to minimize API calls.
The batch buffer is configurable through the client options:
```typescript
const client = new ReflagClient({
batchOptions: {
maxSize: 100, // Maximum number of events to batch
intervalMs: 1000, // Flush interval in milliseconds
},
});
```
You can manually flush the batch buffer at any time:
```typescript
await client.flush();
```
{% hint style="success" %}
It's recommended to call `flush()` before your application shuts down to ensure all events are sent.
{% endhint %}
### Rate Limiting
The SDK includes automatic rate limiting for flag events to prevent overwhelming the API.
Rate limiting is applied per unique combination of flag key and context. The rate limiter window size is configurable:
```typescript
const client = new ReflagClient({
rateLimiterOptions: {
windowSizeMs: 60000, // Rate limiting window size in milliseconds
},
});
```
### Flag definitions
Flag definitions include the rules needed to determine which flags should be enabled and which config values should be applied to any given user/company.
Flag definitions are automatically fetched when calling `initialize()`.
They are then cached and refreshed in the background.
It's also possible to get the currently in use flag definitions:
```typescript
import fs from "fs";
const client = new ReflagClient();
const flagDefs = await client.getFlagDefinitions();
// [{
// key: "huddle",
// description: "Live voice conversations with colleagues."
// flag: { ... }
// config: { ... }
// }]
```
## Bootstrapping client-side applications
The `getFlagsForBootstrap()` method is designed for server-side rendering (SSR) scenarios where you need to pass flag data to client-side applications. This method returns raw flag data without wrapper functions, making it suitable for serialization and client-side hydration.
```typescript
const client = new ReflagClient();
await client.initialize();
// Get flags for bootstrapping with full context
const { context, flags } = client.getFlagsForBootstrap({
user: {
id: "user123",
name: "John Doe",
email: "[email protected]",
},
company: {
id: "company456",
name: "Acme Inc",
plan: "enterprise",
},
other: {
source: "web",
platform: "desktop",
},
});
// Pass this data to your client-side application
// The flags object contains raw flag data suitable for JSON serialization
console.log(flags);
// {
// "huddle": {
// "key": "huddle",
// "isEnabled": true,
// "config": {
// "key": "enhanced",
// "payload": { "maxParticipants": 50, "videoQuality": "hd" },
// }
// }
// }
```
You can also use a bound client for simpler API:
```typescript
const boundClient = client.bindClient({
user: { id: "user123", name: "John Doe", email: "[email protected]" },
company: { id: "company456", name: "Acme Inc", plan: "enterprise" },
});
const { context, flags } = boundClient.getFlagsForBootstrap();
```
### Key differences from `getFlags()`
- **Raw data**: Returns plain objects without `track()` functions, making them JSON serializable
- **Context included**: Returns both the evaluated flags and the context used for evaluation
- **Bootstrapping focus**: Designed specifically for passing data to client-side applications
## Edge-runtimes like Cloudflare Workers
To use the Reflag NodeSDK with Cloudflare workers, set the `node_compat` flag [in your wrangler file](https://developers.cloudflare.com/workers/runtime-apis/nodejs/#get-started).
Instead of using `ReflagClient`, use `EdgeClient` and make sure you call `ctx.waitUntil(reflag.flush());` before returning from your worker function.
```typescript
import { EdgeClient } from "@reflag/node-sdk";
// set the REFLAG_SECRET_KEY environment variable or pass the secret key in the constructor
const reflag = new EdgeClient();
export default {
async fetch(request, _env, ctx): Promise<Response> {
// initialize the client and wait for it to complete
// if the client was initialized on a previous invocation, this is a no-op.
await reflag.initialize();
const flags = reflag.getFlags({
user: { id: "userId" },
company: { id: "companyId" },
});
// ensure all events are flushed and any requests to refresh the flag cache
// have completed after the response is sent
ctx.waitUntil(reflag.flush());
return new Response(
`Flags for user ${userId} and company ${companyId}: ${JSON.stringify(flags, null, 2)}`,
);
},
};
```
See [examples/cloudflare-worker](https://github.com/reflagcom/javascript/tree/main/packages/node-sdk/examples/cloudflare-worker/src/index.ts) for a deployable example.
Reflag maintains a cached set of flag definitions in the memory of your worker which it uses to decide which flags to turn on for which users/companies.
The SDK caches flag definitions in memory for fast performance. The first request to a new worker instance fetches definitions from Reflag's servers, while subsequent requests use the cache. When the cache expires, it's updated in the background. `ctx.waitUntil(reflag.flush())` ensures completion of the background work, so response times are not affected. This background work may increase wall-clock time for your worker, but it will not measurably increase billable CPU time on platforms like Cloudflare.
## Error Handling
The SDK is designed to fail gracefully and never throw exceptions to the caller. Instead, it logs errors and provides
fallback behavior:
1. **Flag Evaluation Failures**:
```typescript
const { isEnabled } = client.getFlag("my-flag");
// If flag evaluation fails, isEnabled will be false
```
2. **Network Errors**:
```typescript
// Network errors during tracking are logged but don't affect your application
const { isEnabled, track } = client.getFlag("my-flag");
if (isEnabled) {
// network errors are caught internally and logged and never bubbled up to your application
// no need to try/catch around "track" or "getFlag"
await track();
}
```
3. **Missing Context**:
```typescript
// The SDK tracks missing context fields but continues operation
const flags = client.getFlags({
user: { id: "user123" },
// Missing company context will be logged but won't cause errors
});
```
4. **Offline Mode**:
```typescript
// In offline mode, the SDK uses flag overrides
const client = new ReflagClient({
offline: true,
flagOverrides: () => ({
"my-flag": true,
}),
});
```
The SDK logs all errors with appropriate severity levels. You can customize logging by providing your own logger:
```typescript
const client = new ReflagClient({
logger: {
debug: (msg) => console.debug(msg),
info: (msg) => console.info(msg),
warn: (msg) => console.warn(msg),
error: (msg, error) => {
console.error(msg, error);
// Send to your error tracking service
errorTracker.capture(error);
},
},
});
```
## Remote config
Remote config is a dynamic and flexible approach to configuring flag behavior outside of your app – without needing to re-deploy it.
Similar to `isEnabled`, each flag has a `config` property. This configuration is managed from within Reflag.
It is managed similar to the way access to flags is managed, but instead of the binary `isEnabled` you can have
multiple configuration values which are given to different user/companies.
```ts
const flags = reflagClient.getFlags();
// {
// huddle: {
// isEnabled: true,
// targetingVersion: 42,
// config: {
// key: "gpt-3.5",
// payload: { maxTokens: 10000, model: "gpt-3.5-beta1" }
// }
// }
// }
```
`key` is mandatory for a config, but if a flag has no config or no config value was matched against the context, the `key` will be `undefined`. Make sure to check against this case when trying to use the configuration in your application. `payload` is an optional JSON value for arbitrary configuration needs.
Just as `isEnabled`, accessing `config` on the object returned by `getFlags` does not automatically
generate a `check` event, contrary to the `config` property on the object returned by `getFlag`.
## Configuring
The Reflag `Node.js` SDK can be configured through environment variables,
a configuration file on disk or by passing options to the `ReflagClient`
constructor. By default, the SDK searches for `reflag.config.json` in the
current working directory.
| Option | Type | Description | Env Var |
| --------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- |
| `secretKey` | string | The secret key used for authentication with Reflag's servers. | REFLAG_SECRET_KEY |
| `logLevel` | string | The log level for the SDK (e.g., `"DEBUG"`, `"INFO"`, `"WARN"`, `"ERROR"`). Default: `INFO` | REFLAG_LOG_LEVEL |
| `offline` | boolean | Operate in offline mode. Default: `false`, except in tests it will default to `true` based off of the `TEST` env. var. | REFLAG_OFFLINE |
| `apiBaseUrl` | string | The base API URL for the Reflag servers. | REFLAG_API_BASE_URL |
| `flagOverrides` | Record<string, boolean> | An object specifying flag overrides for testing or local development. See [examples/express/app.test.ts](https://github.com/reflagcom/javascript/tree/main/packages/node-sdk/examples/express/app.test.ts) for how to use `flagOverrides` in tests. | REFLAG_FLAGS_ENABLED, REFLAG_FLAGS_DISABLED |
| `configFile` | string | Load this config file from disk. Default: `reflag.config.json` | REFLAG_CONFIG_FILE |
{% hint style="info" %}
{% endhint %}
`reflag.config.json` example:
```json
{
"secretKey": "...",
"logLevel": "warn",
"offline": true,
"apiBaseUrl": "https://proxy.slick-demo.com",
"flagOverrides": {
"huddles": true,
"voiceChat": { "isEnabled": false },
"aiAssist": {
"isEnabled": true,
"config": {
"key": "gpt-4.0",
"payload": {
"maxTokens": 50000
}
}
}
}
}
```
When using a `reflag.config.json` for local development, make sure you add it to your
`.gitignore` file. You can also set these options directly in the `ReflagClient`
constructor. The precedence for configuration options is as follows, listed in the
order of importance:
1. Options passed along to the constructor directly,
2. Environment variable,
3. The config file.
## Type safe flags
To get type checked flags, install the Reflag CLI:
```sh
npm i --save-dev @reflag/cli
```
then generate the types:
```sh
npx reflag flags types
```
This will generate a `reflag.d.ts` containing all your flags.
Any flag look ups will now be checked against the flags that exist in Reflag.
Here's an example of a failed type check:
```typescript
import { ReflagClient } from "@reflag/node-sdk";
export const reflagClient = new ReflagClient();
reflagClient.initialize().then(() => {
console.log("Reflag initialized!");
// TypeScript will catch this error: "invalid-flag" doesn't exist
reflagClient.getFlag("invalid-flag");
const {
isEnabled,
config: { payload },
} = reflagClient.getFlag("create-todos");
});
```

This is an example of a failed config payload check:
```typescript
reflagClient.initialize().then(() => {
// TypeScript will catch this error as well: "minLength" is not part of the payload.
if (isEnabled && todo.length > config.payload.minLength) {
// ...
}
});
```

## Testing
When writing tests that cover code with flags, you can toggle flags on/off programmatically to test the different behavior.
`reflag.ts`:
```typescript
import { ReflagClient } from "@reflag/node-sdk";
export const reflag = new ReflagClient();
```
`app.test.ts`:
```typescript
import { reflag } from "./reflag.ts";
beforeAll(async () => await reflag.initialize());
afterEach(() => {
reflag.clearFlagOverrides();
});
describe("API Tests", () => {
it("should return 200 for the root endpoint", async () => {
reflag.flagOverrides = {
"show-todo": true,
};
const response = await request(app).get("/");
expect(response.status).toBe(200);
expect(response.body).toEqual({ message: "Ready to manage some TODOs!" });
});
});
```
See more on flag overrides in the section below.
## Flag Overrides
Flag overrides allow you to override flags and their configurations locally. This is particularly useful for development and testing. You can specify overrides in three ways:
1. Through environment variables:
```bash
REFLAG_FLAGS_ENABLED=flag1,flag2
REFLAG_FLAGS_DISABLED=flag3,flag4
```
1. Through `reflag.config.json`:
```json
{
"flagOverrides": {
"delete-todos": {
"isEnabled": true,
"config": {
"key": "dev-config",
"payload": {
"requireConfirmation": true,
"maxDeletionsPerDay": 5
}
}
}
}
}
```
1. Programmatically through the client options:
You can use a simple `Record<string, boolean>` and pass it either in the constructor or by setting `client.flagOverrides`:
```typescript
// pass directly in the constructor
const client = new ReflagClient({ flagOverrides: { myFlag: true } });
// or set on the client at a later time
client.flagOverrides = { myFlag: false };
// clear flag overrides. Same as setting to {}.
client.clearFlagOverrides();
```
To get dynamic overrides, use a function which takes a context and returns a boolean or an object with the shape of `{isEnabled, config}`:
```typescript
import { ReflagClient, Context } from "@reflag/node-sdk";
const flagOverrides = (context: Context) => ({
"delete-todos": {
isEnabled: true,
config: {
key: "dev-config",
payload: {
requireConfirmation: true,
maxDeletionsPerDay: 5,
},
},
},
});
const client = new ReflagClient({
flagOverrides,
});
```
## Remote Flag Evaluation
In addition to local flag evaluation, Reflag supports remote evaluation using stored context. This is useful when you want to evaluate flags using user/company attributes that were previously sent to Reflag:
```typescript
// First, update user and company attributes
await client.updateUser("user123", {
attributes: {
role: "admin",
subscription: "premium",
},
});
await client.updateCompany("company456", {
attributes: {
tier: "enterprise",
employees: 1000,
},
});
// Later, evaluate flags remotely using stored context
const flags = await client.getFlagsRemote("company456", "user123");
// Or evaluate a single flag
const flag = await client.getFlagRemote(
"create-todos",
"company456",
"user123",
);
// You can also provide additional context
const flagsWithContext = await client.getFlagsRemote("company456", "user123", {
other: {
location: "US",
platform: "mobile",
},
});
```
Remote evaluation is particularly useful when:
- You want to use the most up-to-date user/company attributes stored in Reflag
- You don't want to pass all context attributes with every evaluation
- You need to ensure consistent flag evaluation across different services
## Using with Express
A popular way to integrate the Reflag Node.js SDK is through an express middleware.
```typescript
import reflag from "./reflag";
import express from "express";
import { BoundReflagClient } from "@reflag/node-sdk";
// Augment the Express types to include a `boundReflagClient` property on the
// `res.locals` object.
// This will allow us to access the ReflagClient instance in our route handlers
// without having to pass it around manually
declare global {
namespace Express {
interface Locals {
boundReflagClient: BoundReflagClient;
}
}
}
// Add express middleware
app.use((req, res, next) => {
// Extract the user and company IDs from the request
// You'll want to use a proper authentication and identification
// mechanism in a real-world application
const user = {
id: req.user?.id,
name: req.user?.name,
email: req.user?.email
}
const company = {
id: req.user?.companyId,
name: req.user?.companyName
}
// Create a new BoundReflagClient instance by calling the `bindClient`
// method on a `ReflagClient` instance
// This will create a new instance that is bound to the user/company given.
const boundReflagClient = reflag.bindClient({ user, company });
// Store the BoundReflagClient instance in the `res.locals` object so we
// can access it in our route handlers
res.locals.boundReflagClient = boundReflagClient;
next();
});
// Now use res.locals.boundReflagClient in your handlers
app.get("/todos", async (_req, res) => {
const { track, isEnabled } = res.locals.boundReflagClient.getFlag("show-todos");
if (!isEnabled) {
res.status(403).send({"error": "flag inaccessible"})
return
}
...
}
```
See [examples/express/app.ts](https://github.com/reflagcom/javascript/tree/main/packages/node-sdk/example/express/app.ts) for a full example.
## Remote flag evaluation with stored context
If you don't want to provide context each time when evaluating flags but
rather you would like to utilize the attributes you sent to Reflag previously
(by calling `updateCompany` and `updateUser`) you can do so by calling `getFlagsRemote`
(or `getFlagRemote` for a specific flag) with providing just `userId` and `companyId`.
These methods will call Reflag's servers and flags will be evaluated remotely
using the stored attributes.
```typescript
// Update user and company attributes
client.updateUser("john_doe", {
attributes: {
name: "John O.",
role: "admin",
},
});
client.updateCompany("acme_inc", {
attributes: {
name: "Acme, Inc",
tier: "premium"
},
});
...
// This will evaluate flags with respecting the attributes sent previously
const flags = await client.getFlagsRemote("acme_inc", "john_doe");
```
{% hint style="warning" %}
User and company attribute updates are processed asynchronously, so there might
be a small delay between when attributes are updated and when they are available
for evaluation.
{% endhint %}
## Opting out of tracking
There are use cases in which you not want to be sending `user`, `company` and
`track` events to [Reflag.com](https://reflag.com). These are usually cases where you could be impersonating
another user in the system and do not want to interfere with the data being
collected by Reflag.
To disable tracking, bind the client using `bindClient()` as follows:
```typescript
// binds the client to a given user and company and set `enableTracking` to `false`.
const boundClient = client.bindClient({ user, company, enableTracking: false });
boundClient.track("some event"); // this will not actually send the event to Reflag.
// the following code will not update the `user` nor `company` in Reflag and will
// not send `track` events either.
const { isEnabled, track } = boundClient.getFlag("user-menu");
if (isEnabled) {
track();
}
```
Another way way to disable tracking without employing a bound client is to call `getFlag()`
or `getFlags()` by supplying `enableTracking: false` in the arguments passed to
these functions.
{% hint style="warning" %}
Note, however, that calling `track()`, `updateCompany()` or `updateUser()` in the `ReflagClient`
will still send tracking data. As such, it is always recommended to use `bindClient()`
when using this SDK.
{% endhint %}
## Flushing
ReflagClient employs a batching technique to minimize the number of calls that are sent to
Reflag's servers.
By default, the SDK automatically subscribes to process exit signals and attempts to flush
any pending events. This behavior is controlled by the `flushOnExit` option in the client configuration:
```typescript
const client = new ReflagClient({
batchOptions: {
flushOnExit: false, // disable automatic flushing on exit
},
});
```
## Tracking custom events and setting custom attributes
Tracking allows events and updating user/company attributes in Reflag.
For example, if a customer changes their plan, you'll want Reflag to know about it,
in order to continue to provide up-do-date targeting information in the Reflag interface.
The following example shows how to register a new user, associate it with a company
and finally update the plan they are on.
```typescript
// registers the user with Reflag using the provided unique ID, and
// providing a set of custom attributes (can be anything)
client.updateUser("user_id", {
attributes: { longTimeUser: true, payingCustomer: false },
});
client.updateCompany("company_id", { userId: "user_id" });
// the user started a voice huddle
client.track("user_id", "huddle", { attributes: { voice: true } });
```
It's also possible to achieve the same through a bound client in the following manner:
```typescript
const boundClient = client.bindClient({
user: { id: "user_id", longTimeUser: true, payingCustomer: false },
company: { id: "company_id" },
});
boundClient.track("huddle", { attributes: { voice: true } });
```
Some attributes are used by Reflag to improve the UI, and are recommended
to provide for easier navigation:
- `name` -- display name for `user`/`company`,
- `email` -- the email of the user,
- `avatar` -- the URL for `user`/`company` avatar image.
Attributes cannot be nested (multiple levels) and must be either strings,
integers or booleans.
## Managing `Last seen`
By default `updateUser`/`updateCompany` calls automatically update the given
user/company `Last seen` property on Reflag servers.
You can control if `Last seen` should be updated when the events are sent by setting
`meta.active = false`. This is often useful if you
have a background job that goes through a set of companies just to update their
attributes but not their activity.
Example:
```typescript
client.updateUser("john_doe", {
attributes: { name: "John O." },
meta: { active: true },
});
client.updateCompany("acme_inc", {
attributes: { name: "Acme, Inc" },
meta: { active: false },
});
```
`bindClient()` updates attributes on the Reflag servers but does not automatically
update `Last seen`.
## Zero PII
The Reflag SDK doesn't collect any metadata and HTTP IP addresses are _not_ being
stored. For tracking individual users, we recommend using something like database
ID as userId, as it's unique and doesn't include any PII (personal identifiable
information). If, however, you're using e.g. email address as userId, but prefer
not to send any PII to Reflag, you can hash the sensitive data before sending
it to Reflag:
```typescript
import { sha256 } from 'crypto-hash';
client.updateUser({ userId: await sha256("john_doe"), ... });
```
## Migrating from Bucket SDK
If you have been using the Bucket SDKs previously, the following list will help you migrate to Reflag SDK:
- `Bucket*` classes, and types have been renamed to `Reflag*` (e.g. `BucketClient` is now `ReflagClient`)
- `Feature*` classes, and types have been renamed to `Flag*` (e.g. `Feature` is now `Flag`, `RawFeatures` is now `RawFlags`)
- When using strongly-typed flags, the new `Flags` interface replaced `Features` interface
- All methods that contained `feature` in the name have been renamed to use the `flag` terminology (e.g. `getFeature` is `getFlag`)
- All environment variables that were prefixed with `BUCKET_` are now prefixed with `REFLAG_`
- The `BUCKET_HOST` environment variable and `host` option have been removed from `ReflagClient` constructor, use `REFLAG_API_BASE_URL` instead
- The `BUCKET_FEATURES_ENABLED` and `BUCKET_FEATURES_DISABLED` have been renamed to `REFLAG_FLAGS_ENABLED` and `REFLAG_FLAGS_DISABLED`
- The default configuration file has been renamed from `bucketConfig.json` to `reflag.config.json`
- The `fallbackFeatures` property in client constructor and configuration files has been renamed to `fallbackFlags`
- `featureKey` has been renamed to `flagKey` in all methods that accepts that argument
- The SDKs will not emit `evaluate` and `evaluate-config` events anymore
## Typescript
Types are bundled together with the library and exposed automatically when importing
through a package manager.
## License
> MIT License
> Copyright (c) 2025 Bucket ApS
```
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
```json
{
"cSpell.words": [
"gitbook",
"Reflag"
]
}
```
--------------------------------------------------------------------------------
/.gitbook/includes/need-some-help-chat-with-us.md:
--------------------------------------------------------------------------------
```markdown
---
title: Need some help? Chat with us
---
* Need some help? [Chat with us](mailto:[email protected])
```
--------------------------------------------------------------------------------
/support/get-support.md:
--------------------------------------------------------------------------------
```markdown
---
description: Need support? We're here to help
---
# Get support
* Need some help? [Chat with us](mailto:[email protected])
* Do you prefer a video call? [Talk to a founder](https://reflag.com/contact)
```
--------------------------------------------------------------------------------
/product-handbook/concepts/feature-view.md:
--------------------------------------------------------------------------------
```markdown
# Flag view
### Definition
A view is a simple grouping of multiple [flags](feature.md). It offers the ability to set up notifications and generally see the details of the associated flags in one glance.
### Next steps
* Learn how to [manage views](../feature-views.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/introduction/concepts/feature-view.md:
--------------------------------------------------------------------------------
```markdown
# Feature view
### Definition
A feature view is a simple grouping of multiple [features](feature.md). It offers the ability to set up notifications and generally see the details of the associated features in one glance.
### Next steps
* Learn how to [manage feature views](../../product-handbook/feature-views.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/integrations/overview.md:
--------------------------------------------------------------------------------
```markdown
---
description: Integrate Reflag with your stack.
---
# Overview
## All integrations
These integrations are crafted and maintained by the Reflag team.
{% include "../.gitbook/includes/integrations.md" %}
## **Build your own**
To build your own integrations with Reflag, you can use:
* [Event listeners](../sdk/@reflag/browser-sdk/#event-listeners)
* [HTTP API](../api/public-api/)
**To request support for more integrations,** [**please fill out this form**](https://share-eu1.hsforms.com/14DktM5t6T229b5Bg8KPDBg2b6w1x) **— Thanks!**
```
--------------------------------------------------------------------------------
/product-handbook/concepts/release-stage.md:
--------------------------------------------------------------------------------
```markdown
# Release stage
### Definition
Release stages in Reflag are entities that allow setting up [app](app.md)-wide [feature access](feature.md#access) targeting rules. Each release stage defines [targeting rules](targeting-rules.md) for each available [environment](environment.md). Later, during the development of new features, you can apply all those rule automatically by selecting an available release stage.
Release stages are useful tools when a standard release workflow is used in your organization.
### Next steps
* Learn about [filters](filter.md) and [targeting rules](targeting-rules.md)
```
--------------------------------------------------------------------------------
/supported-languages/overview.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
Reflag SDKs for React, Vue.js, Node.js, Next.js, and more. Supports
OpenFeature.
---
# Overview
## Official SDKs
These SDKs are crafted and maintained by the Reflag team.
{% include "../.gitbook/includes/sdks.md" %}
## Unofficial SDKs
The following SDKs are community-led.
* [Ruby on Rails](ruby-rails-stimulus.md) by [mikker](https://gist.github.com/mikker)
For non-supported languages, you can use the [HTTP API](../api/public-api/).
To request support for more languages, [please fill out this form](https://share-eu1.hsforms.com/14DktM5t6T229b5Bg8KPDBg2b6w1x). 
```
--------------------------------------------------------------------------------
/introduction/concepts/release-stage.md:
--------------------------------------------------------------------------------
```markdown
# Release stage
### Definition
Release stages in Reflag are entities that allow setting up [app](app.md)-wide [feature access](feature.md#access) targeting rules. Each release stage defines [targeting rules](targeting-rules.md) for each available [environment](environment.md). Later, during the development of new features, you can apply all those rule automatically by selecting an available release stage.
Release stages are useful tools when a standard release workflow is used in your organization.
### Next steps
* Learn about [filters](filter.md) and [targeting rules](targeting-rules.md),
* Learn how to [manage release stages](broken-reference) within Reflag UI.
```
--------------------------------------------------------------------------------
/supported-languages/ruby-rails-stimulus.md:
--------------------------------------------------------------------------------
```markdown
---
description: How to use Reflag with Rails and Stimulus
hidden: true
---
# Ruby SDK
How to use Reflag with Rails (+ Stimulus). Created by [mikker](https://gist.github.com/mikker) on [GitHub](https://gist.github.com/mikker/c435fc6bfcbdf67b60cd12ff96a45ee5).
{% embed url="https://gist.github.com/mikker/c435fc6bfcbdf67b60cd12ff96a45ee5#file-application-html-erb" %}
{% embed url="https://gist.github.com/mikker/c435fc6bfcbdf67b60cd12ff96a45ee5#file-application_controller-rb" %}
{% embed url="https://gist.github.com/mikker/c435fc6bfcbdf67b60cd12ff96a45ee5#file-bucket_controller-js" %}
{% embed url="https://gist.github.com/mikker/c435fc6bfcbdf67b60cd12ff96a45ee5#file-index-html-erb" %}
```
--------------------------------------------------------------------------------
/product-handbook/creating-and-managing-apps.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about apps in Reflag
---
# Managing apps
Learn about [apps](../introduction/concepts/app.md) here.
### Modifying or deleting an app
* On the sidebar, click `Settings`
* Under the `App:[App Name]` heading, click `General`
* You can modify the `App name`
* You can delete the app by clicking the `Delete app` button
<figure><img src="../.gitbook/assets/Modifying or deleting an app-min.png" alt="Reflag Global Settings page"><figcaption></figcaption></figure>
### Creating a new app
If you have multiple products or applications, you can create additional apps.
* Click on `[Current app name]`, found in the top-left corner
* In the tab that appears, click `New app`
* Name the app and click `Create`
```
--------------------------------------------------------------------------------
/product-handbook/launch-monitor/give-feedback-button.md:
--------------------------------------------------------------------------------
```markdown
---
description: Adding a feedback button using Reflag SDKs in a few lines of code.
---
# Give feedback button
Collecting feedback through a "Give feedback" button is a great way to collect feedback from users.
Here's a brief example using the [Reflag React SDK](../../sdk/@reflag/browser-sdk/):
```tsx
import { useFlag } from "@reflag/react-sdk";
function StartHuddleButton() {
const { isLoading, isEnabled, track, requestFeedback } = useFlag("huddle");
if (isLoading) {
return <Loading />;
}
if (!isEnabled) {
return null;
}
return (
<>
<button onClick={track}>Start huddle!</button>
<button
onClick={() => requestFeedback({ title: "How do you like Huddles?" })}
>
Give feedback!
</button>
</>
);
}
```
```
--------------------------------------------------------------------------------
/product-handbook/concepts/app.md:
--------------------------------------------------------------------------------
```markdown
# App
An **app** maps to a product or application that you track within Reflag. You can have multiple apps setup within Reflag.
An app can have multiple [environments](environment.md) with features within it.
### Definition
An **app** maps to a product or application that you track within Reflag. You can have multiple apps setup within Reflag.
The following entities are managed at the app level: 
* [Features](feature.md)
* [Feature views](feature-view.md)
* [Company segments](segment.md)
* [Release stages](release-stage.md)
While the definitions of features and company segments are app-wide, the data they aggregate is [environment](environment.md) specific.
### Next steps
* Learn about [features](feature.md) or [company segments](segment.md),
* Learn how to [manage your apps](../creating-and-managing-apps/) within Reflag UI.
\
\
```
--------------------------------------------------------------------------------
/introduction/concepts/app.md:
--------------------------------------------------------------------------------
```markdown
# App
An **app** maps to a product or application that you track within Reflag. You can have multiple apps setup within Reflag.
An app can have multiple [environments](environment.md) with features within it.
### Definition
An **app** maps to a product or application that you track within Reflag. You can have multiple apps setup within Reflag.
The following entities are managed at the app level: 
* [Features](feature.md)
* [Feature views](feature-view.md)
* [Company segments](segment.md)
* [Release stages](release-stage.md)
While the definitions of features and company segments are app-wide, the data they aggregate is [environment](environment.md) specific.
### Next steps
* Learn about [features](feature.md) or [company segments](segment.md),
* Learn how to [manage your apps](../../product-handbook/creating-and-managing-apps.md) within Reflag UI.
\
\
```
--------------------------------------------------------------------------------
/integrations/segment.md:
--------------------------------------------------------------------------------
```markdown
---
description: Use Segment events for tracking feature adoption metrics on Reflag
---
# Segment
Reflag's segment integration is for customers who already use Segment for event tracking and want to use those events for tracking feature adoption metrics on Reflag.
## Getting started
1. Set up [Reflag Cloud destination](https://app.segment.com/goto-my-workspace/destinations/catalog/bucket) to receive data from a Segment source.
<figure><img src="../.gitbook/assets/Screenshot 2025-09-09 at 09.32.31.png" alt=""><figcaption></figcaption></figure>
2. Copy your **Reflag Publishable key** from the Environments page in Settings and add it to the `API Key` settings field in the destination.
3. Enable the destination.
4. Check the Tracking page in Reflag to ensure the data arrives. Data should start flowing immediately.
## Supported types
Reflag supports `analytics.track(),` `analytics.identify()` and `analytics.group()` , but doesn't support the Segment `analytics.page()` , which are ignored.
```
--------------------------------------------------------------------------------
/api/reflag-rest-api/reflag-api-reference.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
Describes the REST API that allows clients to manage and update apps, flags
and related entities.
---
# API Reference
{% openapi-operation spec="reflag-api" path="/apps" method="get" %}
[OpenAPI reflag-api](https://app.reflag.com/openapi.json)
{% endopenapi-operation %}
{% openapi-operation spec="reflag-api" path="/apps/{appId}" method="get" %}
[OpenAPI reflag-api](https://app.reflag.com/openapi.json)
{% endopenapi-operation %}
{% openapi-operation spec="reflag-api" path="/apps/{appId}/flags" method="get" %}
[OpenAPI reflag-api](https://app.reflag.com/openapi.json)
{% endopenapi-operation %}
{% openapi-operation spec="reflag-api" path="/apps/{appId}/flags/{flagKey}/targeting/{envId}" method="get" %}
[OpenAPI reflag-api](https://app.reflag.com/openapi.json)
{% endopenapi-operation %}
{% openapi-operation spec="reflag-api" path="/apps/{appId}/flags/specific-targets/{envId}" method="patch" %}
[OpenAPI reflag-api](https://app.reflag.com/openapi.json)
{% endopenapi-operation %}
```
--------------------------------------------------------------------------------
/integrations/cursor.md:
--------------------------------------------------------------------------------
```markdown
---
description: How to create feature flags in Cursor
---
# Cursor
### Rule
Create a Project Rule called `.cursor/rules/featureflags.md`. Here's a template you can use:
```markdown
We use Reflag (https://reflag.com) for feature flagging and feature management.
Reflag's documentation is located at https://docs.reflag.com
You can create feature flags using the CLI (@reflag/cli).
If installed, you can use the the Reflag MCP to create flags.
Alternatively, try this command to use the Reflag CLI: npx reflag new
```
### Slash Command
Create a slash command called `.cursor/commands/flag.md` Here's a template you can use:
```
Feature flag the changes
1. Create a feature flag with Reflag with an appropriate name
2. Update the code to ensure changes are flagged
The Reflag documentation is located at https://docs.reflag.com
If installed, use the CLI to create a feature flag using the command: npx reflag new
If the Reflag MCP is installed, you can create a flag through the Reflag MCP
```
### MCP
See [mcp.md](../api/mcp.md "mention") page for Cursor instructions
```
--------------------------------------------------------------------------------
/product-handbook/concepts/feedback.md:
--------------------------------------------------------------------------------
```markdown
# Feedback
### Definition
A feedback entity in Reflag is sent by the client when an user provides feedback within your application. You must be using Reflag SDKs to gain access to feedback collection functionality. Feedback can be submitted by the user when your application triggers the collection manually, or automatically, when [automatic feedback surveys](../launch-monitor/automated-feedback-surveys.md) are enabled.
### Collected data
The feedback, submitted by an user of your application will contain the following details:
* The [user](user.md) and user's [company](company.md) IDs,
* The [feature key](feature.md#feature-key) for which the feedback is provided,
* The **score**, if configured to ask for one,
* A **free-form message**, if configured to ask for one.
* A **feedback request** ID if the feedback was submitted in response to an automatic request from Reflag.
All feedback is collected in Reflag and used for various metrics.
### Next steps
* Learn how to set up [automatic feedback surveys](../launch-monitor/automated-feedback-surveys.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/product-handbook/feature-views.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about views in Reflag
---
# Feature views
## What are views?
Views group features in a single view to let you organize features as well as enable and customize Slack reporting and column configurations.
## Creating views
You can create and manage views in the [App Settings](https://app.reflag.com/env-current/settings/app-stages). You can create new views, edit existing views, and enable weekly reporting to Slack.
<figure><img src="../.gitbook/assets/Screenshot 2025-09-12 at 15.16.42.png" alt=""><figcaption></figcaption></figure>
## Adding and removing flags to views
To add a flag to a view, go to the [flag](https://app.reflag.com/env-current/features) you want to add to a view. In the right-hand sidebar, click on the + icon beside "Add to views" to add it to a view. You'll have the option to select an existing view or create a new one.
You can remove a feature from a view simply by clicking on the X icon.
<figure><img src="../.gitbook/assets/Screenshot 2025-09-12 at 15.18.42.png" alt="Adding a feature to a feature view"><figcaption></figcaption></figure>
```
--------------------------------------------------------------------------------
/supported-languages/openfeature.md:
--------------------------------------------------------------------------------
```markdown
---
description: Reflag provides OpenFeature integration for use in browser (Web) and Node.js
---
# OpenFeature
## What is OpenFeature? <a href="#what-is-the-react-sdk" id="what-is-the-react-sdk"></a>
From [openfeature.dev](https://openfeature.dev):
> OpenFeature is an open specification that provides a vendor-agnostic, community-driven API for feature flagging that works with your favorite feature flag management tool.
Reflag provides OpenFeature integration for use in browser (Web) and Node.js.
## Getting started <a href="#getting-started" id="getting-started"></a>
Reflag providers are [listed on openfeature.dev](https://openfeature.dev/ecosystem?instant_search%5Bquery%5D=reflag)
Documentation:
* [OpenFeature Node.js provider](https://github.com/reflagcom/javascript/blob/main/packages/openfeature-node-provider/README.md)
* [OpenFeature Browser provider](https://github.com/reflagcom/javascript/tree/main/packages/openfeature-browser-provider)
## Further documentation <a href="#install-the-sdk" id="install-the-sdk"></a>
[Learn about OpenFeature providers](https://openfeature.dev/docs/reference/concepts/provider) on the official docs
```
--------------------------------------------------------------------------------
/introduction/concepts/feedback.md:
--------------------------------------------------------------------------------
```markdown
# Feedback
### Definition
A feedback entity in Reflag is sent by the client when an user provides feedback within your application. You must be using Reflag SDKs to gain access to feedback collection functionality. Feedback can be submitted by the user when your application triggers the collection manually, or automatically, when [automatic feedback surveys](../../product-handbook/launch-monitor/automated-feedback-surveys.md) are enabled.
### Collected data
The feedback, submitted by an user of your application will contain the following details:
* The [user](user.md) and user's [company](company.md) IDs,
* The [feature key](feature.md#feature-key) for which the feedback is provided,
* The **score**, if configured to ask for one,
* A **free-form message**, if configured to ask for one.
* A **feedback request** ID if the feedback was submitted in response to an automatic request from Reflag.
All feedback is collected in Reflag and used for various metrics including [STARS](broken-reference).
### Next steps
* Learn how to set up [automatic feedback surveys](../../product-handbook/launch-monitor/automated-feedback-surveys.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/integrations/github.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
Integrate GitHub to automatically check feature flag code references and
receive automatic AI code clean-up pull requests
---
# GitHub
Using the integration for GitHub, Reflag does two things:
* Automatically searches your repository for references to feature flags. This way you can know if a flag was cleaned up from your codebase or whether it's still being used. See how the clean-up guide uses this in [feature-clean-up-and-archival-beta](../product-handbook/feature-clean-up-and-archival-beta/ "mention").
* Reflag can automatically clean up your code once a feature has been rolled out to everyone. See [ai-code-clean-up-beta.md](../product-handbook/feature-clean-up-and-archival-beta/ai-code-clean-up-beta.md "mention") for more information.
{% hint style="info" %}
GitHub integration is available on Pro and Enterprise [plans](https://reflag.com/pricing)
{% endhint %}
## Connect to GitHub
Connecting to GitHub happens at the Organization level. Go to [Organization settings](https://app.reflag.com/env-current/settings/org-integrations) and:
1. Click "Connect" for the GitHub integration.
2. You'll be taken to an authentication consent screen.
3. Once you've approved, you'll need to pick a repository.
```
--------------------------------------------------------------------------------
/product-handbook/data-residency.md:
--------------------------------------------------------------------------------
```markdown
---
description: Reflag on data residency
---
# Data residency
When you sign up with Reflag you automatically use our global infrastructure to guarantee low latency from your users' clients to our servers. 
However, if you need your users' data to stay inside the EU you can contact us at [email protected] and request we change your data residency to EU only.
By default, our SDKs connect to `front.reflag.com`. This points to our globally distributed edge servers and requests to this domain will be served generally by a server closest to the user. 
However, if you're using the EU data residency, you must change the `apiBaseUrl` to `front-eu.reflag.com` when configuring the SDK to ensure the requests always land on one of our EU servers.
Here's how you can set the host in our Browser SDK and Node SDK:
```ts
// Browser SDK + Node SDK
const reflagClient = new ReflagClient({
publishableKey: "{YOUR_PUBLISHABLE_KEY}",
apiBaseUrl: "https://front-eu.reflag.com",
...
});
```
And using the React SDK:
```tsx
// React SDK
import { ReflagProvider } from "@reflag/react-sdk";
<ReflagProvider
publishableKey="{YOUR_PUBLISHABLE_KEY}"
company={{ id: "acme_inc" }}
user={{ id: "john doe" }}
apiBaseUrl="https://front-eu.reflag.com"
>
...
</ReflagProvider>
```
```
--------------------------------------------------------------------------------
/.gitbook/includes/sdks.md:
--------------------------------------------------------------------------------
```markdown
---
title: SDKs
---
<table data-view="cards" data-full-width="true"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>React</td><td><a href="../assets/react.svg">react.svg</a></td><td><a href="../../sdk/@reflag/react-sdk/">react-sdk</a></td></tr><tr><td>Vue.js</td><td><a href="../assets/vue-logo.svg">vue-logo.svg</a></td><td><a href="../../sdk/@reflag/vue-sdk/">vue-sdk</a></td></tr><tr><td>Client-side</td><td><a href="../assets/ts-js.svg">ts-js.svg</a></td><td><a href="../../sdk/@reflag/browser-sdk/">browser-sdk</a></td></tr><tr><td>Server-side</td><td><a href="../assets/node-js.svg">node-js.svg</a></td><td><a href="../../sdk/@reflag/node-sdk/">node-sdk</a></td></tr><tr><td>Next.js</td><td><a href="../assets/next-js.svg">next-js.svg</a></td><td><a href="../../supported-languages/next.js.md">next.js.md</a></td></tr><tr><td>Reflag supports OpenFeature</td><td><a href="../assets/openfeature.svg">openfeature.svg</a></td><td><a href="../../supported-languages/openfeature.md">openfeature.md</a></td></tr><tr><td>Don't use these languages or frameworks? Use our API</td><td><a href="../assets/api.svg">api.svg</a></td><td><a href="../../api/public-api/">public-api</a></td></tr></tbody></table>
```
--------------------------------------------------------------------------------
/.gitbook/includes/languages.md:
--------------------------------------------------------------------------------
```markdown
---
title: Supported languages
---
<table data-view="cards" data-full-width="true"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>React</td><td><a href="../assets/react.svg">react.svg</a></td><td><a href="../../sdk/@reflag/react-sdk/">react-sdk</a></td></tr><tr><td>Vue.js</td><td><a href="../assets/vue-logo.svg">vue-logo.svg</a></td><td><a href="../../sdk/@reflag/vue-sdk/">vue-sdk</a></td></tr><tr><td>Client-side</td><td><a href="../assets/ts-js.svg">ts-js.svg</a></td><td><a href="../../sdk/@reflag/browser-sdk/">browser-sdk</a></td></tr><tr><td>Server-side</td><td><a href="../assets/node-js.svg">node-js.svg</a></td><td><a href="../../sdk/@reflag/node-sdk/">node-sdk</a></td></tr><tr><td>Next.js</td><td><a href="../assets/next-js.svg">next-js.svg</a></td><td><a href="../../supported-languages/next.js.md">next.js.md</a></td></tr><tr><td>Reflag supports OpenFeature</td><td><a href="../assets/openfeature.svg">openfeature.svg</a></td><td><a href="../../supported-languages/openfeature.md">openfeature.md</a></td></tr><tr><td>Don't use these languages or frameworks? Use our API</td><td><a href="../assets/api.svg">api.svg</a></td><td><a href="../../api/public-api/">public-api</a></td></tr></tbody></table>
```
--------------------------------------------------------------------------------
/product-handbook/feature-entitlements/simple-role-based-entitlements.md:
--------------------------------------------------------------------------------
```markdown
---
description: Learn more about simple role-based entitlements in Reflag
---
# Simple role-based entitlements
If you need to enforce feature access at the company subscription level _**and**_ user role level (user permissions), you can combine your user role and permission services with Reflag.
For example, let's say your "Export to CSV" feature is only available to customers on the "Business" or "Enterprise" plans _**and**_ only users with the "admin" role should be allowed to use it.
If you have complex user permissions, you likely need to use a dedicated user authentication service with Role-Based Access Control (RBAC) support.
If you have simple and static user permissions, like "admin" and "member", that don't change frequently, you may be able to hard code the access controls.
### Managing simple role-based user permissions
Let's look at how to handle the simple use case with Reflag. 
If you zoom out, this is what controlling feature access at the customer subscription level looks like.
<figure><img src="../../.gitbook/assets/example 1 (1).png" alt=""><figcaption></figcaption></figure>
To add simple user role controls to the mix, you can choose to hard code the user role check within the `isEnabled` check.
<figure><img src="../../.gitbook/assets/example 2 (1).png" alt=""><figcaption></figcaption></figure>
```
--------------------------------------------------------------------------------
/product-handbook/concepts/segment.md:
--------------------------------------------------------------------------------
```markdown
# Segment
### Definition
A segment entity in Reflag is a dynamic collection of [companies](company.md). The dynamic nature of segments arise from the fact that segments use [filters](filter.md) to evaluate which companies are included in the segment.
### Filters
Segment filters can be constructed using any combination of the following rules:
* [company attributes](company.md#attributes), 
* [user feature access](feature.md#access), 
* [feature metrics](feature.md#metrics),
* other segments
{% hint style="info" %}
Segments with a filter that uses `First Seen`, `Last Seen` company attribute rules or feature metric rules cannot be used in [targeting rules](targeting-rules.md). By extension, other segments depend on these segments, also cannot be used in targeting rules.
{% endhint %}
### Environments
All segments in Reflag are [app](app.md)-wide. This means that the same segment will share the same settings (including filters) across all the [environments](environment.md) in the app.
It is up to you to populate the data in the environments you define in such a way that segments would pick up companies properly. Another option is to create separate segments for different environments.
### Next steps
* Learn about [users](user.md), [filters](filter.md) and [targeting rules](targeting-rules.md).
* Learn how to [create company segments](../creating-segments.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/integrations/mixpanel.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
How Reflag integrates with Mixpanel to query analytics based on feature access
filters
---
# Mixpanel
With the Mixpanel integration, you can attach feature access properties to users and groups on Mixpanel. This will enable you to query analytics based on feature access filters.
### Get available features from Reflag
In this example, we're using the [Browser SDK](../sdk/@reflag/browser-sdk/):
```javascript
//init
const reflag = new ReflagBrowserSDK.ReflagClient({
publishableKey: "pub_prod_5eS0G5hX4ZOpwoAw1CKTeP",
user: {
id: "u1234",
name: "Rasmus Makwarth",
},
});
//get features
const features = reflag.getFeatures();
```
This will return JSON with all available features for the authenticated user:
```json
"features": {
"export-to-csv": {
"isEnabled": true,
"key": "export-to-csv",
"targetingVersion": 2
},
...
}
```
### Add as property on Mixpanel
We can forward all features or pick certain features and send access state to Mixpanel. Here we send an array of features that the user has access to:
```javascript
mixpanel.identify("u1234");
mixpanel.people.set({
$name: "Rasmus Makwarth",
$features: ["export-to-csv"],
});
```
Which will look like this on Mixpanel:
<figure><img src="../.gitbook/assets/CleanShot 2025-01-09 at 11 .11.54@2x (1).png" alt=""><figcaption></figcaption></figure>
You may want to add the property to the user's group as well.
```
--------------------------------------------------------------------------------
/introduction/concepts/segment.md:
--------------------------------------------------------------------------------
```markdown
# Segment
### Definition
A segment entity in Reflag is a dynamic collection of [companies](company.md). The dynamic nature of segments arise from the fact that segments use [filters](filter.md) to evaluate which companies are included in the segment.
### Filters
Segment filters can be constructed using any combination of the following rules:
* [company attributes](company.md#attributes), 
* [user feature access](feature.md#access), 
* [feature metrics](feature.md#metrics),
* other segments
{% hint style="info" %}
Segments with a filter that uses `First Seen`, `Last Seen` company attribute rules or feature metric rules cannot be used in [targeting rules](targeting-rules.md). By extension, other segments depend on these segments, also cannot be used in targeting rules.
{% endhint %}
### Environments
All segments in Reflag are [app](app.md)-wide. This means that the same segment will share the same settings (including filters) across all the [environments](environment.md) in the app.
It is up to you to populate the data in the environments you define in such a way that segments would pick up companies properly. Another option is to create separate segments for different environments.
### Next steps
* Learn about [users](user.md), [filters](filter.md) and [targeting rules](targeting-rules.md).
* Learn how to [create company segments](../../product-handbook/feature-targeting-rules/creating-segments.md) within Reflag UI.
```
--------------------------------------------------------------------------------
/.gitbook/includes/untitled.md:
--------------------------------------------------------------------------------
```markdown
---
title: Untitled
---
<table data-view="cards" data-full-width="true"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><a href="../../integrations/slack.md"><strong>Slack</strong></a></td><td></td><td></td><td><a href="../assets/slack.svg">slack.svg</a></td></tr><tr><td><a href="../../integrations/linear.md"><strong>Linear</strong></a></td><td></td><td></td><td><a href="../assets/linear.svg">linear.svg</a></td></tr><tr><td><a href="../../integrations/segment.md"><strong>Segment</strong></a></td><td></td><td></td><td><a href="../assets/segment.svg">segment.svg</a></td></tr><tr><td><a href="../../integrations/datadog.md">Datadog</a></td><td></td><td></td><td><a href="../assets/datadog.svg">datadog.svg</a></td></tr><tr><td><a href="../../integrations/posthog.md"><strong>PostHog</strong></a></td><td></td><td></td><td><a href="../assets/posthog.svg">posthog.svg</a></td></tr><tr><td><a href="../../integrations/amplitude.md"><strong>Amplitude</strong></a></td><td></td><td></td><td><a href="../assets/amplitude.svg">amplitude.svg</a></td></tr><tr><td><a href="../../integrations/mixpanel.md"><strong>Mixpanel</strong></a></td><td></td><td></td><td><a href="../assets/mixpanel.svg">mixpanel.svg</a></td></tr><tr><td><a href="../../integrations/aws-s3.md"><strong>AWS S3</strong></a></td><td></td><td></td><td><a href="../assets/aws-s3.svg">aws-s3.svg</a></td></tr></tbody></table>
```
--------------------------------------------------------------------------------
/integrations/posthog.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
How Reflag integrates with PostHog to query analytics based on feature access
filters
---
# PostHog
With the PostHog integration, you can attach feature access properties to users and groups on PostHog. This will enable you to query analytics based on feature access filters.
### Get available features from Reflag
In this example, we're using the [@reflag/browser-sdk](../sdk/@reflag/browser-sdk/):
```javascript
//init
const reflag = new ReflagBrowserSDK.ReflagClient({
publishableKey: "pub_prod_5eS0G5hX4ZOpwoAw1CKTeP",
user: {
id: "u1234",
name: "Rasmus Makwarth",
},
});
//get features
const features = reflag.getFeatures();
```
This will return JSON with all available features for the authenticated user:
```json
"features": {
"export-to-csv": {
"isEnabled": true,
"key": "export-to-csv",
"targetingVersion": 2
},
...
}
```
### Add as property on PostHog
We can forward all features or pick certain features and send access state to PostHog:
<pre class="language-tsx"><code class="lang-tsx"><strong>posthog.identify("u1234", {
</strong> name: "Rasmus Makwarth",
features: {
"export-to-csv": {
isEnabled: true,
},
},
});
</code></pre>
Which will look like this on PostHog:
<figure><img src="../.gitbook/assets/CleanShot 2025-01-09 at 9 [email protected]" alt=""><figcaption></figcaption></figure>
You may want to add the property to the user's group as well.
```
--------------------------------------------------------------------------------
/integrations/amplitude.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
How Reflag integrates with Amplitude to query analytics based on feature
access filters
---
# Amplitude
With the Amplitude integration, you can attach feature access properties to users and groups on Amplitude. This will enable you to query analytics based on feature access filters.
### Get available features from Reflag
In this example, we're using the [Browser SDK](../sdk/@reflag/browser-sdk/):
```javascript
//init
const reflag = new ReflagBrowserSDK.ReflagClient({
publishableKey: "pub_prod_5eS0G5hX4ZOpwoAw1CKTeP",
user: {
id: "u1234",
name: "Rasmus Makwarth",
},
});
//get features
const features = reflag.getFeatures();
```
This will return JSON with all available features for the authenticated user:
```json
"features": {
"export-to-csv": {
"isEnabled": true,
"key": "export-to-csv",
"targetingVersion": 2
},
...
}
```
### Add as property on Amplitude
We can forward all features or pick certain features and send access state to Amplitude. Here we send an array of features that the user has access to:
```javascript
amplitude.setUserId("u1234");
const identifyEvent = new amplitude.Identify();
identifyEvent.append("features", "export-to-csv");
amplitude.identify(identifyEvent);
```
Which will look like this on Amplitude:
<figure><img src="../.gitbook/assets/CleanShot 2025-01-09 at 10 [email protected]" alt=""><figcaption></figcaption></figure>
You may want to add the property to the user's group as well.
```
--------------------------------------------------------------------------------
/integrations/datadog.md:
--------------------------------------------------------------------------------
```markdown
---
description: >-
How Reflag integrates with Datadog to catch regressions on new feature
releases
---
# Datadog
With the Datadog integration, you can enrich your RUM data with feature flag data. This will enable you to catch regressions on new feature releases.
### Get available features from Reflag
In this example, we're using the [React SDK](../sdk/@reflag/browser-sdk/):
```javascript
import { datadogRum } from "@datadog/browser-rum";
import { useClient } from "@reflag/react-sdk";
// Component to enhnance datadog RUM with flag checks
function DatadogIntegration() {
const client = useClient();
useEffect(() => {
return client?.on("check", (check) => {
datadogRum.addFeatureFlagEvaluation(check.key, check.value);
});
}, [client]);
return null;
}
```
Add the component inside the ReflagProvider:
```tsx
function App() {
return (
<ReflagProvider>
<DatadogIntegration /> // Add the component inside the <ReflagProvider>
{children}
</ReflagProvider>
)
}
```
Which will look like this on Datadog:
<figure><img src="../.gitbook/assets/feature-flag-list-rum-event.d9c1c876a34458edc70d1317efaec05b.png.avif" alt=""><figcaption></figcaption></figure>
<figure><img src="../.gitbook/assets/rum-explorer-session-feature-flag-search.435802460fd607608ad5155f029da57b.png.avif" alt=""><figcaption></figcaption></figure>
<figure><img src="../.gitbook/assets/rum-explorer-error-feature-flag-search.7b9f6c046db1de1c71d279c139f1508a.png.avif" alt=""><figcaption></figcaption></figure>
```
--------------------------------------------------------------------------------
/integrations/slack.md:
--------------------------------------------------------------------------------
```markdown
---
description: Integrate Slack to get notified about new feature changes and feedback
---
# Slack
With the integration for Slack, you can get notifications whenever a feature's access and/or stage changes and whenever an end-user submit feature feedback. You can also get a feature view report.
## Authenticate with Slack
Authentication happens at the environment level. Once you've authenticated, all environments, apps and features can be connected to Slack.
* Go to **Settings**
* Select **Slack** under Environment.
<figure><img src="../.gitbook/assets/slackDisconnected (1).png" alt=""><figcaption><p>Click "Connect to Slack" to authenticate</p></figcaption></figure>
## Choose default Slack channel
You can set a default Slack channel for an app. This means that all features within the app will all inherit the default channel unless you overwrite it.
* Go to Settings
* Select **Slack** under **Environment: Production**
Note: Slack notifications are only supported in the Production [environment](../product-handbook/concepts/environment.md).
<figure><img src="../.gitbook/assets/slackConnected (1).png" alt=""><figcaption><p>Choose default Slack channel for this app's production environment</p></figcaption></figure>
## Available Slack notifications
<table><thead><tr><th width="557">What</th><th>When</th></tr></thead><tbody><tr><td>Feature access or state changes</td><td>Real-time</td></tr><tr><td>Feature archive updates</td><td>Real-time</td></tr><tr><td>Feature feedback submissions</td><td>Real-time</td></tr></tbody></table>
```